##// END OF EJS Templates
dirstate: add a synchronisation point before doing a full dirstate read...
marmoute -
r51123:fc8e37c3 stable
parent child Browse files
Show More
@@ -1,2902 +1,2912 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
8
9 import functools
9 import functools
10 import re
10 import re
11
11
12 from . import (
12 from . import (
13 encoding,
13 encoding,
14 error,
14 error,
15 )
15 )
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 = b"extension '%s' overwrite config item '%s.%s'"
25 msg = b"extension '%s' overwrite config item '%s.%s'"
26 msg %= (extname, section, key)
26 msg %= (extname, section, key)
27 ui.develwarn(msg, config=b'warn-config')
27 ui.develwarn(msg, config=b'warn-config')
28
28
29 knownitems.update(items)
29 knownitems.update(items)
30
30
31
31
32 class configitem:
32 class configitem:
33 """represent a known config item
33 """represent a known config item
34
34
35 :section: the official config section where to find this item,
35 :section: the official config section where to find this item,
36 :name: the official name within the section,
36 :name: the official name within the section,
37 :default: default value for this item,
37 :default: default value for this item,
38 :alias: optional list of tuples as alternatives,
38 :alias: optional list of tuples as alternatives,
39 :generic: this is a generic definition, match name using regular expression.
39 :generic: this is a generic definition, match name using regular expression.
40 """
40 """
41
41
42 def __init__(
42 def __init__(
43 self,
43 self,
44 section,
44 section,
45 name,
45 name,
46 default=None,
46 default=None,
47 alias=(),
47 alias=(),
48 generic=False,
48 generic=False,
49 priority=0,
49 priority=0,
50 experimental=False,
50 experimental=False,
51 ):
51 ):
52 self.section = section
52 self.section = section
53 self.name = name
53 self.name = name
54 self.default = default
54 self.default = default
55 self.alias = list(alias)
55 self.alias = list(alias)
56 self.generic = generic
56 self.generic = generic
57 self.priority = priority
57 self.priority = priority
58 self.experimental = experimental
58 self.experimental = experimental
59 self._re = None
59 self._re = None
60 if generic:
60 if generic:
61 self._re = re.compile(self.name)
61 self._re = re.compile(self.name)
62
62
63
63
64 class itemregister(dict):
64 class itemregister(dict):
65 """A specialized dictionary that can handle wild-card selection"""
65 """A specialized dictionary that can handle wild-card selection"""
66
66
67 def __init__(self):
67 def __init__(self):
68 super(itemregister, self).__init__()
68 super(itemregister, self).__init__()
69 self._generics = set()
69 self._generics = set()
70
70
71 def update(self, other):
71 def update(self, other):
72 super(itemregister, self).update(other)
72 super(itemregister, self).update(other)
73 self._generics.update(other._generics)
73 self._generics.update(other._generics)
74
74
75 def __setitem__(self, key, item):
75 def __setitem__(self, key, item):
76 super(itemregister, self).__setitem__(key, item)
76 super(itemregister, self).__setitem__(key, item)
77 if item.generic:
77 if item.generic:
78 self._generics.add(item)
78 self._generics.add(item)
79
79
80 def get(self, key):
80 def get(self, key):
81 baseitem = super(itemregister, self).get(key)
81 baseitem = super(itemregister, self).get(key)
82 if baseitem is not None and not baseitem.generic:
82 if baseitem is not None and not baseitem.generic:
83 return baseitem
83 return baseitem
84
84
85 # search for a matching generic item
85 # search for a matching generic item
86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 for item in generics:
87 for item in generics:
88 # we use 'match' instead of 'search' to make the matching simpler
88 # we use 'match' instead of 'search' to make the matching simpler
89 # for people unfamiliar with regular expression. Having the match
89 # for people unfamiliar with regular expression. Having the match
90 # rooted to the start of the string will produce less surprising
90 # rooted to the start of the string will produce less surprising
91 # result for user writing simple regex for sub-attribute.
91 # result for user writing simple regex for sub-attribute.
92 #
92 #
93 # For example using "color\..*" match produces an unsurprising
93 # For example using "color\..*" match produces an unsurprising
94 # result, while using search could suddenly match apparently
94 # result, while using search could suddenly match apparently
95 # unrelated configuration that happens to contains "color."
95 # unrelated configuration that happens to contains "color."
96 # anywhere. This is a tradeoff where we favor requiring ".*" on
96 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 # some match to avoid the need to prefix most pattern with "^".
97 # some match to avoid the need to prefix most pattern with "^".
98 # The "^" seems more error prone.
98 # The "^" seems more error prone.
99 if item._re.match(key):
99 if item._re.match(key):
100 return item
100 return item
101
101
102 return None
102 return None
103
103
104
104
105 coreitems = {}
105 coreitems = {}
106
106
107
107
108 def _register(configtable, *args, **kwargs):
108 def _register(configtable, *args, **kwargs):
109 item = configitem(*args, **kwargs)
109 item = configitem(*args, **kwargs)
110 section = configtable.setdefault(item.section, itemregister())
110 section = configtable.setdefault(item.section, itemregister())
111 if item.name in section:
111 if item.name in section:
112 msg = b"duplicated config item registration for '%s.%s'"
112 msg = b"duplicated config item registration for '%s.%s'"
113 raise error.ProgrammingError(msg % (item.section, item.name))
113 raise error.ProgrammingError(msg % (item.section, item.name))
114 section[item.name] = item
114 section[item.name] = item
115
115
116
116
117 # special value for case where the default is derived from other values
117 # special value for case where the default is derived from other values
118 dynamicdefault = object()
118 dynamicdefault = object()
119
119
120 # Registering actual config items
120 # Registering actual config items
121
121
122
122
123 def getitemregister(configtable):
123 def getitemregister(configtable):
124 f = functools.partial(_register, configtable)
124 f = functools.partial(_register, configtable)
125 # export pseudo enum as configitem.*
125 # export pseudo enum as configitem.*
126 f.dynamicdefault = dynamicdefault
126 f.dynamicdefault = dynamicdefault
127 return f
127 return f
128
128
129
129
130 coreconfigitem = getitemregister(coreitems)
130 coreconfigitem = getitemregister(coreitems)
131
131
132
132
133 def _registerdiffopts(section, configprefix=b''):
133 def _registerdiffopts(section, configprefix=b''):
134 coreconfigitem(
134 coreconfigitem(
135 section,
135 section,
136 configprefix + b'nodates',
136 configprefix + b'nodates',
137 default=False,
137 default=False,
138 )
138 )
139 coreconfigitem(
139 coreconfigitem(
140 section,
140 section,
141 configprefix + b'showfunc',
141 configprefix + b'showfunc',
142 default=False,
142 default=False,
143 )
143 )
144 coreconfigitem(
144 coreconfigitem(
145 section,
145 section,
146 configprefix + b'unified',
146 configprefix + b'unified',
147 default=None,
147 default=None,
148 )
148 )
149 coreconfigitem(
149 coreconfigitem(
150 section,
150 section,
151 configprefix + b'git',
151 configprefix + b'git',
152 default=False,
152 default=False,
153 )
153 )
154 coreconfigitem(
154 coreconfigitem(
155 section,
155 section,
156 configprefix + b'ignorews',
156 configprefix + b'ignorews',
157 default=False,
157 default=False,
158 )
158 )
159 coreconfigitem(
159 coreconfigitem(
160 section,
160 section,
161 configprefix + b'ignorewsamount',
161 configprefix + b'ignorewsamount',
162 default=False,
162 default=False,
163 )
163 )
164 coreconfigitem(
164 coreconfigitem(
165 section,
165 section,
166 configprefix + b'ignoreblanklines',
166 configprefix + b'ignoreblanklines',
167 default=False,
167 default=False,
168 )
168 )
169 coreconfigitem(
169 coreconfigitem(
170 section,
170 section,
171 configprefix + b'ignorewseol',
171 configprefix + b'ignorewseol',
172 default=False,
172 default=False,
173 )
173 )
174 coreconfigitem(
174 coreconfigitem(
175 section,
175 section,
176 configprefix + b'nobinary',
176 configprefix + b'nobinary',
177 default=False,
177 default=False,
178 )
178 )
179 coreconfigitem(
179 coreconfigitem(
180 section,
180 section,
181 configprefix + b'noprefix',
181 configprefix + b'noprefix',
182 default=False,
182 default=False,
183 )
183 )
184 coreconfigitem(
184 coreconfigitem(
185 section,
185 section,
186 configprefix + b'word-diff',
186 configprefix + b'word-diff',
187 default=False,
187 default=False,
188 )
188 )
189
189
190
190
191 coreconfigitem(
191 coreconfigitem(
192 b'alias',
192 b'alias',
193 b'.*',
193 b'.*',
194 default=dynamicdefault,
194 default=dynamicdefault,
195 generic=True,
195 generic=True,
196 )
196 )
197 coreconfigitem(
197 coreconfigitem(
198 b'auth',
198 b'auth',
199 b'cookiefile',
199 b'cookiefile',
200 default=None,
200 default=None,
201 )
201 )
202 _registerdiffopts(section=b'annotate')
202 _registerdiffopts(section=b'annotate')
203 # bookmarks.pushing: internal hack for discovery
203 # bookmarks.pushing: internal hack for discovery
204 coreconfigitem(
204 coreconfigitem(
205 b'bookmarks',
205 b'bookmarks',
206 b'pushing',
206 b'pushing',
207 default=list,
207 default=list,
208 )
208 )
209 # bundle.mainreporoot: internal hack for bundlerepo
209 # bundle.mainreporoot: internal hack for bundlerepo
210 coreconfigitem(
210 coreconfigitem(
211 b'bundle',
211 b'bundle',
212 b'mainreporoot',
212 b'mainreporoot',
213 default=b'',
213 default=b'',
214 )
214 )
215 coreconfigitem(
215 coreconfigitem(
216 b'censor',
216 b'censor',
217 b'policy',
217 b'policy',
218 default=b'abort',
218 default=b'abort',
219 experimental=True,
219 experimental=True,
220 )
220 )
221 coreconfigitem(
221 coreconfigitem(
222 b'chgserver',
222 b'chgserver',
223 b'idletimeout',
223 b'idletimeout',
224 default=3600,
224 default=3600,
225 )
225 )
226 coreconfigitem(
226 coreconfigitem(
227 b'chgserver',
227 b'chgserver',
228 b'skiphash',
228 b'skiphash',
229 default=False,
229 default=False,
230 )
230 )
231 coreconfigitem(
231 coreconfigitem(
232 b'cmdserver',
232 b'cmdserver',
233 b'log',
233 b'log',
234 default=None,
234 default=None,
235 )
235 )
236 coreconfigitem(
236 coreconfigitem(
237 b'cmdserver',
237 b'cmdserver',
238 b'max-log-files',
238 b'max-log-files',
239 default=7,
239 default=7,
240 )
240 )
241 coreconfigitem(
241 coreconfigitem(
242 b'cmdserver',
242 b'cmdserver',
243 b'max-log-size',
243 b'max-log-size',
244 default=b'1 MB',
244 default=b'1 MB',
245 )
245 )
246 coreconfigitem(
246 coreconfigitem(
247 b'cmdserver',
247 b'cmdserver',
248 b'max-repo-cache',
248 b'max-repo-cache',
249 default=0,
249 default=0,
250 experimental=True,
250 experimental=True,
251 )
251 )
252 coreconfigitem(
252 coreconfigitem(
253 b'cmdserver',
253 b'cmdserver',
254 b'message-encodings',
254 b'message-encodings',
255 default=list,
255 default=list,
256 )
256 )
257 coreconfigitem(
257 coreconfigitem(
258 b'cmdserver',
258 b'cmdserver',
259 b'track-log',
259 b'track-log',
260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 )
261 )
262 coreconfigitem(
262 coreconfigitem(
263 b'cmdserver',
263 b'cmdserver',
264 b'shutdown-on-interrupt',
264 b'shutdown-on-interrupt',
265 default=True,
265 default=True,
266 )
266 )
267 coreconfigitem(
267 coreconfigitem(
268 b'color',
268 b'color',
269 b'.*',
269 b'.*',
270 default=None,
270 default=None,
271 generic=True,
271 generic=True,
272 )
272 )
273 coreconfigitem(
273 coreconfigitem(
274 b'color',
274 b'color',
275 b'mode',
275 b'mode',
276 default=b'auto',
276 default=b'auto',
277 )
277 )
278 coreconfigitem(
278 coreconfigitem(
279 b'color',
279 b'color',
280 b'pagermode',
280 b'pagermode',
281 default=dynamicdefault,
281 default=dynamicdefault,
282 )
282 )
283 coreconfigitem(
283 coreconfigitem(
284 b'command-templates',
284 b'command-templates',
285 b'graphnode',
285 b'graphnode',
286 default=None,
286 default=None,
287 alias=[(b'ui', b'graphnodetemplate')],
287 alias=[(b'ui', b'graphnodetemplate')],
288 )
288 )
289 coreconfigitem(
289 coreconfigitem(
290 b'command-templates',
290 b'command-templates',
291 b'log',
291 b'log',
292 default=None,
292 default=None,
293 alias=[(b'ui', b'logtemplate')],
293 alias=[(b'ui', b'logtemplate')],
294 )
294 )
295 coreconfigitem(
295 coreconfigitem(
296 b'command-templates',
296 b'command-templates',
297 b'mergemarker',
297 b'mergemarker',
298 default=(
298 default=(
299 b'{node|short} '
299 b'{node|short} '
300 b'{ifeq(tags, "tip", "", '
300 b'{ifeq(tags, "tip", "", '
301 b'ifeq(tags, "", "", "{tags} "))}'
301 b'ifeq(tags, "", "", "{tags} "))}'
302 b'{if(bookmarks, "{bookmarks} ")}'
302 b'{if(bookmarks, "{bookmarks} ")}'
303 b'{ifeq(branch, "default", "", "{branch} ")}'
303 b'{ifeq(branch, "default", "", "{branch} ")}'
304 b'- {author|user}: {desc|firstline}'
304 b'- {author|user}: {desc|firstline}'
305 ),
305 ),
306 alias=[(b'ui', b'mergemarkertemplate')],
306 alias=[(b'ui', b'mergemarkertemplate')],
307 )
307 )
308 coreconfigitem(
308 coreconfigitem(
309 b'command-templates',
309 b'command-templates',
310 b'pre-merge-tool-output',
310 b'pre-merge-tool-output',
311 default=None,
311 default=None,
312 alias=[(b'ui', b'pre-merge-tool-output-template')],
312 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 )
313 )
314 coreconfigitem(
314 coreconfigitem(
315 b'command-templates',
315 b'command-templates',
316 b'oneline-summary',
316 b'oneline-summary',
317 default=None,
317 default=None,
318 )
318 )
319 coreconfigitem(
319 coreconfigitem(
320 b'command-templates',
320 b'command-templates',
321 b'oneline-summary.*',
321 b'oneline-summary.*',
322 default=dynamicdefault,
322 default=dynamicdefault,
323 generic=True,
323 generic=True,
324 )
324 )
325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 coreconfigitem(
326 coreconfigitem(
327 b'commands',
327 b'commands',
328 b'commit.post-status',
328 b'commit.post-status',
329 default=False,
329 default=False,
330 )
330 )
331 coreconfigitem(
331 coreconfigitem(
332 b'commands',
332 b'commands',
333 b'grep.all-files',
333 b'grep.all-files',
334 default=False,
334 default=False,
335 experimental=True,
335 experimental=True,
336 )
336 )
337 coreconfigitem(
337 coreconfigitem(
338 b'commands',
338 b'commands',
339 b'merge.require-rev',
339 b'merge.require-rev',
340 default=False,
340 default=False,
341 )
341 )
342 coreconfigitem(
342 coreconfigitem(
343 b'commands',
343 b'commands',
344 b'push.require-revs',
344 b'push.require-revs',
345 default=False,
345 default=False,
346 )
346 )
347 coreconfigitem(
347 coreconfigitem(
348 b'commands',
348 b'commands',
349 b'resolve.confirm',
349 b'resolve.confirm',
350 default=False,
350 default=False,
351 )
351 )
352 coreconfigitem(
352 coreconfigitem(
353 b'commands',
353 b'commands',
354 b'resolve.explicit-re-merge',
354 b'resolve.explicit-re-merge',
355 default=False,
355 default=False,
356 )
356 )
357 coreconfigitem(
357 coreconfigitem(
358 b'commands',
358 b'commands',
359 b'resolve.mark-check',
359 b'resolve.mark-check',
360 default=b'none',
360 default=b'none',
361 )
361 )
362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 coreconfigitem(
363 coreconfigitem(
364 b'commands',
364 b'commands',
365 b'show.aliasprefix',
365 b'show.aliasprefix',
366 default=list,
366 default=list,
367 )
367 )
368 coreconfigitem(
368 coreconfigitem(
369 b'commands',
369 b'commands',
370 b'status.relative',
370 b'status.relative',
371 default=False,
371 default=False,
372 )
372 )
373 coreconfigitem(
373 coreconfigitem(
374 b'commands',
374 b'commands',
375 b'status.skipstates',
375 b'status.skipstates',
376 default=[],
376 default=[],
377 experimental=True,
377 experimental=True,
378 )
378 )
379 coreconfigitem(
379 coreconfigitem(
380 b'commands',
380 b'commands',
381 b'status.terse',
381 b'status.terse',
382 default=b'',
382 default=b'',
383 )
383 )
384 coreconfigitem(
384 coreconfigitem(
385 b'commands',
385 b'commands',
386 b'status.verbose',
386 b'status.verbose',
387 default=False,
387 default=False,
388 )
388 )
389 coreconfigitem(
389 coreconfigitem(
390 b'commands',
390 b'commands',
391 b'update.check',
391 b'update.check',
392 default=None,
392 default=None,
393 )
393 )
394 coreconfigitem(
394 coreconfigitem(
395 b'commands',
395 b'commands',
396 b'update.requiredest',
396 b'update.requiredest',
397 default=False,
397 default=False,
398 )
398 )
399 coreconfigitem(
399 coreconfigitem(
400 b'committemplate',
400 b'committemplate',
401 b'.*',
401 b'.*',
402 default=None,
402 default=None,
403 generic=True,
403 generic=True,
404 )
404 )
405 coreconfigitem(
405 coreconfigitem(
406 b'convert',
406 b'convert',
407 b'bzr.saverev',
407 b'bzr.saverev',
408 default=True,
408 default=True,
409 )
409 )
410 coreconfigitem(
410 coreconfigitem(
411 b'convert',
411 b'convert',
412 b'cvsps.cache',
412 b'cvsps.cache',
413 default=True,
413 default=True,
414 )
414 )
415 coreconfigitem(
415 coreconfigitem(
416 b'convert',
416 b'convert',
417 b'cvsps.fuzz',
417 b'cvsps.fuzz',
418 default=60,
418 default=60,
419 )
419 )
420 coreconfigitem(
420 coreconfigitem(
421 b'convert',
421 b'convert',
422 b'cvsps.logencoding',
422 b'cvsps.logencoding',
423 default=None,
423 default=None,
424 )
424 )
425 coreconfigitem(
425 coreconfigitem(
426 b'convert',
426 b'convert',
427 b'cvsps.mergefrom',
427 b'cvsps.mergefrom',
428 default=None,
428 default=None,
429 )
429 )
430 coreconfigitem(
430 coreconfigitem(
431 b'convert',
431 b'convert',
432 b'cvsps.mergeto',
432 b'cvsps.mergeto',
433 default=None,
433 default=None,
434 )
434 )
435 coreconfigitem(
435 coreconfigitem(
436 b'convert',
436 b'convert',
437 b'git.committeractions',
437 b'git.committeractions',
438 default=lambda: [b'messagedifferent'],
438 default=lambda: [b'messagedifferent'],
439 )
439 )
440 coreconfigitem(
440 coreconfigitem(
441 b'convert',
441 b'convert',
442 b'git.extrakeys',
442 b'git.extrakeys',
443 default=list,
443 default=list,
444 )
444 )
445 coreconfigitem(
445 coreconfigitem(
446 b'convert',
446 b'convert',
447 b'git.findcopiesharder',
447 b'git.findcopiesharder',
448 default=False,
448 default=False,
449 )
449 )
450 coreconfigitem(
450 coreconfigitem(
451 b'convert',
451 b'convert',
452 b'git.remoteprefix',
452 b'git.remoteprefix',
453 default=b'remote',
453 default=b'remote',
454 )
454 )
455 coreconfigitem(
455 coreconfigitem(
456 b'convert',
456 b'convert',
457 b'git.renamelimit',
457 b'git.renamelimit',
458 default=400,
458 default=400,
459 )
459 )
460 coreconfigitem(
460 coreconfigitem(
461 b'convert',
461 b'convert',
462 b'git.saverev',
462 b'git.saverev',
463 default=True,
463 default=True,
464 )
464 )
465 coreconfigitem(
465 coreconfigitem(
466 b'convert',
466 b'convert',
467 b'git.similarity',
467 b'git.similarity',
468 default=50,
468 default=50,
469 )
469 )
470 coreconfigitem(
470 coreconfigitem(
471 b'convert',
471 b'convert',
472 b'git.skipsubmodules',
472 b'git.skipsubmodules',
473 default=False,
473 default=False,
474 )
474 )
475 coreconfigitem(
475 coreconfigitem(
476 b'convert',
476 b'convert',
477 b'hg.clonebranches',
477 b'hg.clonebranches',
478 default=False,
478 default=False,
479 )
479 )
480 coreconfigitem(
480 coreconfigitem(
481 b'convert',
481 b'convert',
482 b'hg.ignoreerrors',
482 b'hg.ignoreerrors',
483 default=False,
483 default=False,
484 )
484 )
485 coreconfigitem(
485 coreconfigitem(
486 b'convert',
486 b'convert',
487 b'hg.preserve-hash',
487 b'hg.preserve-hash',
488 default=False,
488 default=False,
489 )
489 )
490 coreconfigitem(
490 coreconfigitem(
491 b'convert',
491 b'convert',
492 b'hg.revs',
492 b'hg.revs',
493 default=None,
493 default=None,
494 )
494 )
495 coreconfigitem(
495 coreconfigitem(
496 b'convert',
496 b'convert',
497 b'hg.saverev',
497 b'hg.saverev',
498 default=False,
498 default=False,
499 )
499 )
500 coreconfigitem(
500 coreconfigitem(
501 b'convert',
501 b'convert',
502 b'hg.sourcename',
502 b'hg.sourcename',
503 default=None,
503 default=None,
504 )
504 )
505 coreconfigitem(
505 coreconfigitem(
506 b'convert',
506 b'convert',
507 b'hg.startrev',
507 b'hg.startrev',
508 default=None,
508 default=None,
509 )
509 )
510 coreconfigitem(
510 coreconfigitem(
511 b'convert',
511 b'convert',
512 b'hg.tagsbranch',
512 b'hg.tagsbranch',
513 default=b'default',
513 default=b'default',
514 )
514 )
515 coreconfigitem(
515 coreconfigitem(
516 b'convert',
516 b'convert',
517 b'hg.usebranchnames',
517 b'hg.usebranchnames',
518 default=True,
518 default=True,
519 )
519 )
520 coreconfigitem(
520 coreconfigitem(
521 b'convert',
521 b'convert',
522 b'ignoreancestorcheck',
522 b'ignoreancestorcheck',
523 default=False,
523 default=False,
524 experimental=True,
524 experimental=True,
525 )
525 )
526 coreconfigitem(
526 coreconfigitem(
527 b'convert',
527 b'convert',
528 b'localtimezone',
528 b'localtimezone',
529 default=False,
529 default=False,
530 )
530 )
531 coreconfigitem(
531 coreconfigitem(
532 b'convert',
532 b'convert',
533 b'p4.encoding',
533 b'p4.encoding',
534 default=dynamicdefault,
534 default=dynamicdefault,
535 )
535 )
536 coreconfigitem(
536 coreconfigitem(
537 b'convert',
537 b'convert',
538 b'p4.startrev',
538 b'p4.startrev',
539 default=0,
539 default=0,
540 )
540 )
541 coreconfigitem(
541 coreconfigitem(
542 b'convert',
542 b'convert',
543 b'skiptags',
543 b'skiptags',
544 default=False,
544 default=False,
545 )
545 )
546 coreconfigitem(
546 coreconfigitem(
547 b'convert',
547 b'convert',
548 b'svn.debugsvnlog',
548 b'svn.debugsvnlog',
549 default=True,
549 default=True,
550 )
550 )
551 coreconfigitem(
551 coreconfigitem(
552 b'convert',
552 b'convert',
553 b'svn.trunk',
553 b'svn.trunk',
554 default=None,
554 default=None,
555 )
555 )
556 coreconfigitem(
556 coreconfigitem(
557 b'convert',
557 b'convert',
558 b'svn.tags',
558 b'svn.tags',
559 default=None,
559 default=None,
560 )
560 )
561 coreconfigitem(
561 coreconfigitem(
562 b'convert',
562 b'convert',
563 b'svn.branches',
563 b'svn.branches',
564 default=None,
564 default=None,
565 )
565 )
566 coreconfigitem(
566 coreconfigitem(
567 b'convert',
567 b'convert',
568 b'svn.startrev',
568 b'svn.startrev',
569 default=0,
569 default=0,
570 )
570 )
571 coreconfigitem(
571 coreconfigitem(
572 b'convert',
572 b'convert',
573 b'svn.dangerous-set-commit-dates',
573 b'svn.dangerous-set-commit-dates',
574 default=False,
574 default=False,
575 )
575 )
576 coreconfigitem(
576 coreconfigitem(
577 b'debug',
577 b'debug',
578 b'dirstate.delaywrite',
578 b'dirstate.delaywrite',
579 default=0,
579 default=0,
580 )
580 )
581 coreconfigitem(
581 coreconfigitem(
582 b'debug',
582 b'debug',
583 b'revlog.verifyposition.changelog',
583 b'revlog.verifyposition.changelog',
584 default=b'',
584 default=b'',
585 )
585 )
586 coreconfigitem(
586 coreconfigitem(
587 b'debug',
587 b'debug',
588 b'revlog.debug-delta',
588 b'revlog.debug-delta',
589 default=False,
589 default=False,
590 )
590 )
591 coreconfigitem(
591 coreconfigitem(
592 b'defaults',
592 b'defaults',
593 b'.*',
593 b'.*',
594 default=None,
594 default=None,
595 generic=True,
595 generic=True,
596 )
596 )
597 coreconfigitem(
597 coreconfigitem(
598 b'devel',
598 b'devel',
599 b'all-warnings',
599 b'all-warnings',
600 default=False,
600 default=False,
601 )
601 )
602 coreconfigitem(
602 coreconfigitem(
603 b'devel',
603 b'devel',
604 b'bundle2.debug',
604 b'bundle2.debug',
605 default=False,
605 default=False,
606 )
606 )
607 coreconfigitem(
607 coreconfigitem(
608 b'devel',
608 b'devel',
609 b'bundle.delta',
609 b'bundle.delta',
610 default=b'',
610 default=b'',
611 )
611 )
612 coreconfigitem(
612 coreconfigitem(
613 b'devel',
613 b'devel',
614 b'cache-vfs',
614 b'cache-vfs',
615 default=None,
615 default=None,
616 )
616 )
617 coreconfigitem(
617 coreconfigitem(
618 b'devel',
618 b'devel',
619 b'check-locks',
619 b'check-locks',
620 default=False,
620 default=False,
621 )
621 )
622 coreconfigitem(
622 coreconfigitem(
623 b'devel',
623 b'devel',
624 b'check-relroot',
624 b'check-relroot',
625 default=False,
625 default=False,
626 )
626 )
627 # Track copy information for all file, not just "added" one (very slow)
627 # Track copy information for all file, not just "added" one (very slow)
628 coreconfigitem(
628 coreconfigitem(
629 b'devel',
629 b'devel',
630 b'copy-tracing.trace-all-files',
630 b'copy-tracing.trace-all-files',
631 default=False,
631 default=False,
632 )
632 )
633 coreconfigitem(
633 coreconfigitem(
634 b'devel',
634 b'devel',
635 b'default-date',
635 b'default-date',
636 default=None,
636 default=None,
637 )
637 )
638 coreconfigitem(
638 coreconfigitem(
639 b'devel',
639 b'devel',
640 b'deprec-warn',
640 b'deprec-warn',
641 default=False,
641 default=False,
642 )
642 )
643 # possible values:
643 # possible values:
644 # - auto (the default)
644 # - auto (the default)
645 # - force-append
645 # - force-append
646 # - force-new
646 # - force-new
647 coreconfigitem(
647 coreconfigitem(
648 b'devel',
648 b'devel',
649 b'dirstate.v2.data_update_mode',
649 b'dirstate.v2.data_update_mode',
650 default="auto",
650 default="auto",
651 )
651 )
652 coreconfigitem(
652 coreconfigitem(
653 b'devel',
653 b'devel',
654 b'disableloaddefaultcerts',
654 b'disableloaddefaultcerts',
655 default=False,
655 default=False,
656 )
656 )
657 coreconfigitem(
657 coreconfigitem(
658 b'devel',
658 b'devel',
659 b'warn-empty-changegroup',
659 b'warn-empty-changegroup',
660 default=False,
660 default=False,
661 )
661 )
662 coreconfigitem(
662 coreconfigitem(
663 b'devel',
663 b'devel',
664 b'legacy.exchange',
664 b'legacy.exchange',
665 default=list,
665 default=list,
666 )
666 )
667 # When True, revlogs use a special reference version of the nodemap, that is not
667 # When True, revlogs use a special reference version of the nodemap, that is not
668 # performant but is "known" to behave properly.
668 # performant but is "known" to behave properly.
669 coreconfigitem(
669 coreconfigitem(
670 b'devel',
670 b'devel',
671 b'persistent-nodemap',
671 b'persistent-nodemap',
672 default=False,
672 default=False,
673 )
673 )
674 coreconfigitem(
674 coreconfigitem(
675 b'devel',
675 b'devel',
676 b'servercafile',
676 b'servercafile',
677 default=b'',
677 default=b'',
678 )
678 )
679 coreconfigitem(
679 coreconfigitem(
680 b'devel',
680 b'devel',
681 b'serverexactprotocol',
681 b'serverexactprotocol',
682 default=b'',
682 default=b'',
683 )
683 )
684 coreconfigitem(
684 coreconfigitem(
685 b'devel',
685 b'devel',
686 b'serverrequirecert',
686 b'serverrequirecert',
687 default=False,
687 default=False,
688 )
688 )
689 # Makes the status algorithm wait for the existence of this file
689 # Makes the status algorithm wait for the existence of this file
690 # (or until a timeout of `devel.sync.status.pre-dirstate-write-file-timeout`
690 # (or until a timeout of `devel.sync.status.pre-dirstate-write-file-timeout`
691 # seconds) before taking the lock and writing the dirstate.
691 # seconds) before taking the lock and writing the dirstate.
692 # Status signals that it's ready to wait by creating a file
692 # Status signals that it's ready to wait by creating a file
693 # with the same name + `.waiting`.
693 # with the same name + `.waiting`.
694 # Useful when testing race conditions.
694 # Useful when testing race conditions.
695 coreconfigitem(
695 coreconfigitem(
696 b'devel',
696 b'devel',
697 b'sync.status.pre-dirstate-write-file',
697 b'sync.status.pre-dirstate-write-file',
698 default=None,
698 default=None,
699 )
699 )
700 coreconfigitem(
700 coreconfigitem(
701 b'devel',
701 b'devel',
702 b'sync.status.pre-dirstate-write-file-timeout',
702 b'sync.status.pre-dirstate-write-file-timeout',
703 default=2,
703 default=2,
704 )
704 )
705 coreconfigitem(
705 coreconfigitem(
706 b'devel',
706 b'devel',
707 b'sync.dirstate.pre-read-file',
708 default=None,
709 )
710 coreconfigitem(
711 b'devel',
712 b'sync.dirstate.pre-read-file-timeout',
713 default=2,
714 )
715 coreconfigitem(
716 b'devel',
707 b'strip-obsmarkers',
717 b'strip-obsmarkers',
708 default=True,
718 default=True,
709 )
719 )
710 coreconfigitem(
720 coreconfigitem(
711 b'devel',
721 b'devel',
712 b'warn-config',
722 b'warn-config',
713 default=None,
723 default=None,
714 )
724 )
715 coreconfigitem(
725 coreconfigitem(
716 b'devel',
726 b'devel',
717 b'warn-config-default',
727 b'warn-config-default',
718 default=None,
728 default=None,
719 )
729 )
720 coreconfigitem(
730 coreconfigitem(
721 b'devel',
731 b'devel',
722 b'user.obsmarker',
732 b'user.obsmarker',
723 default=None,
733 default=None,
724 )
734 )
725 coreconfigitem(
735 coreconfigitem(
726 b'devel',
736 b'devel',
727 b'warn-config-unknown',
737 b'warn-config-unknown',
728 default=None,
738 default=None,
729 )
739 )
730 coreconfigitem(
740 coreconfigitem(
731 b'devel',
741 b'devel',
732 b'debug.copies',
742 b'debug.copies',
733 default=False,
743 default=False,
734 )
744 )
735 coreconfigitem(
745 coreconfigitem(
736 b'devel',
746 b'devel',
737 b'copy-tracing.multi-thread',
747 b'copy-tracing.multi-thread',
738 default=True,
748 default=True,
739 )
749 )
740 coreconfigitem(
750 coreconfigitem(
741 b'devel',
751 b'devel',
742 b'debug.extensions',
752 b'debug.extensions',
743 default=False,
753 default=False,
744 )
754 )
745 coreconfigitem(
755 coreconfigitem(
746 b'devel',
756 b'devel',
747 b'debug.repo-filters',
757 b'debug.repo-filters',
748 default=False,
758 default=False,
749 )
759 )
750 coreconfigitem(
760 coreconfigitem(
751 b'devel',
761 b'devel',
752 b'debug.peer-request',
762 b'debug.peer-request',
753 default=False,
763 default=False,
754 )
764 )
755 # If discovery.exchange-heads is False, the discovery will not start with
765 # If discovery.exchange-heads is False, the discovery will not start with
756 # remote head fetching and local head querying.
766 # remote head fetching and local head querying.
757 coreconfigitem(
767 coreconfigitem(
758 b'devel',
768 b'devel',
759 b'discovery.exchange-heads',
769 b'discovery.exchange-heads',
760 default=True,
770 default=True,
761 )
771 )
762 # If discovery.grow-sample is False, the sample size used in set discovery will
772 # If discovery.grow-sample is False, the sample size used in set discovery will
763 # not be increased through the process
773 # not be increased through the process
764 coreconfigitem(
774 coreconfigitem(
765 b'devel',
775 b'devel',
766 b'discovery.grow-sample',
776 b'discovery.grow-sample',
767 default=True,
777 default=True,
768 )
778 )
769 # When discovery.grow-sample.dynamic is True, the default, the sample size is
779 # When discovery.grow-sample.dynamic is True, the default, the sample size is
770 # adapted to the shape of the undecided set (it is set to the max of:
780 # adapted to the shape of the undecided set (it is set to the max of:
771 # <target-size>, len(roots(undecided)), len(heads(undecided)
781 # <target-size>, len(roots(undecided)), len(heads(undecided)
772 coreconfigitem(
782 coreconfigitem(
773 b'devel',
783 b'devel',
774 b'discovery.grow-sample.dynamic',
784 b'discovery.grow-sample.dynamic',
775 default=True,
785 default=True,
776 )
786 )
777 # discovery.grow-sample.rate control the rate at which the sample grow
787 # discovery.grow-sample.rate control the rate at which the sample grow
778 coreconfigitem(
788 coreconfigitem(
779 b'devel',
789 b'devel',
780 b'discovery.grow-sample.rate',
790 b'discovery.grow-sample.rate',
781 default=1.05,
791 default=1.05,
782 )
792 )
783 # If discovery.randomize is False, random sampling during discovery are
793 # If discovery.randomize is False, random sampling during discovery are
784 # deterministic. It is meant for integration tests.
794 # deterministic. It is meant for integration tests.
785 coreconfigitem(
795 coreconfigitem(
786 b'devel',
796 b'devel',
787 b'discovery.randomize',
797 b'discovery.randomize',
788 default=True,
798 default=True,
789 )
799 )
790 # Control the initial size of the discovery sample
800 # Control the initial size of the discovery sample
791 coreconfigitem(
801 coreconfigitem(
792 b'devel',
802 b'devel',
793 b'discovery.sample-size',
803 b'discovery.sample-size',
794 default=200,
804 default=200,
795 )
805 )
796 # Control the initial size of the discovery for initial change
806 # Control the initial size of the discovery for initial change
797 coreconfigitem(
807 coreconfigitem(
798 b'devel',
808 b'devel',
799 b'discovery.sample-size.initial',
809 b'discovery.sample-size.initial',
800 default=100,
810 default=100,
801 )
811 )
802 _registerdiffopts(section=b'diff')
812 _registerdiffopts(section=b'diff')
803 coreconfigitem(
813 coreconfigitem(
804 b'diff',
814 b'diff',
805 b'merge',
815 b'merge',
806 default=False,
816 default=False,
807 experimental=True,
817 experimental=True,
808 )
818 )
809 coreconfigitem(
819 coreconfigitem(
810 b'email',
820 b'email',
811 b'bcc',
821 b'bcc',
812 default=None,
822 default=None,
813 )
823 )
814 coreconfigitem(
824 coreconfigitem(
815 b'email',
825 b'email',
816 b'cc',
826 b'cc',
817 default=None,
827 default=None,
818 )
828 )
819 coreconfigitem(
829 coreconfigitem(
820 b'email',
830 b'email',
821 b'charsets',
831 b'charsets',
822 default=list,
832 default=list,
823 )
833 )
824 coreconfigitem(
834 coreconfigitem(
825 b'email',
835 b'email',
826 b'from',
836 b'from',
827 default=None,
837 default=None,
828 )
838 )
829 coreconfigitem(
839 coreconfigitem(
830 b'email',
840 b'email',
831 b'method',
841 b'method',
832 default=b'smtp',
842 default=b'smtp',
833 )
843 )
834 coreconfigitem(
844 coreconfigitem(
835 b'email',
845 b'email',
836 b'reply-to',
846 b'reply-to',
837 default=None,
847 default=None,
838 )
848 )
839 coreconfigitem(
849 coreconfigitem(
840 b'email',
850 b'email',
841 b'to',
851 b'to',
842 default=None,
852 default=None,
843 )
853 )
844 coreconfigitem(
854 coreconfigitem(
845 b'experimental',
855 b'experimental',
846 b'archivemetatemplate',
856 b'archivemetatemplate',
847 default=dynamicdefault,
857 default=dynamicdefault,
848 )
858 )
849 coreconfigitem(
859 coreconfigitem(
850 b'experimental',
860 b'experimental',
851 b'auto-publish',
861 b'auto-publish',
852 default=b'publish',
862 default=b'publish',
853 )
863 )
854 coreconfigitem(
864 coreconfigitem(
855 b'experimental',
865 b'experimental',
856 b'bundle-phases',
866 b'bundle-phases',
857 default=False,
867 default=False,
858 )
868 )
859 coreconfigitem(
869 coreconfigitem(
860 b'experimental',
870 b'experimental',
861 b'bundle2-advertise',
871 b'bundle2-advertise',
862 default=True,
872 default=True,
863 )
873 )
864 coreconfigitem(
874 coreconfigitem(
865 b'experimental',
875 b'experimental',
866 b'bundle2-output-capture',
876 b'bundle2-output-capture',
867 default=False,
877 default=False,
868 )
878 )
869 coreconfigitem(
879 coreconfigitem(
870 b'experimental',
880 b'experimental',
871 b'bundle2.pushback',
881 b'bundle2.pushback',
872 default=False,
882 default=False,
873 )
883 )
874 coreconfigitem(
884 coreconfigitem(
875 b'experimental',
885 b'experimental',
876 b'bundle2lazylocking',
886 b'bundle2lazylocking',
877 default=False,
887 default=False,
878 )
888 )
879 coreconfigitem(
889 coreconfigitem(
880 b'experimental',
890 b'experimental',
881 b'bundlecomplevel',
891 b'bundlecomplevel',
882 default=None,
892 default=None,
883 )
893 )
884 coreconfigitem(
894 coreconfigitem(
885 b'experimental',
895 b'experimental',
886 b'bundlecomplevel.bzip2',
896 b'bundlecomplevel.bzip2',
887 default=None,
897 default=None,
888 )
898 )
889 coreconfigitem(
899 coreconfigitem(
890 b'experimental',
900 b'experimental',
891 b'bundlecomplevel.gzip',
901 b'bundlecomplevel.gzip',
892 default=None,
902 default=None,
893 )
903 )
894 coreconfigitem(
904 coreconfigitem(
895 b'experimental',
905 b'experimental',
896 b'bundlecomplevel.none',
906 b'bundlecomplevel.none',
897 default=None,
907 default=None,
898 )
908 )
899 coreconfigitem(
909 coreconfigitem(
900 b'experimental',
910 b'experimental',
901 b'bundlecomplevel.zstd',
911 b'bundlecomplevel.zstd',
902 default=None,
912 default=None,
903 )
913 )
904 coreconfigitem(
914 coreconfigitem(
905 b'experimental',
915 b'experimental',
906 b'bundlecompthreads',
916 b'bundlecompthreads',
907 default=None,
917 default=None,
908 )
918 )
909 coreconfigitem(
919 coreconfigitem(
910 b'experimental',
920 b'experimental',
911 b'bundlecompthreads.bzip2',
921 b'bundlecompthreads.bzip2',
912 default=None,
922 default=None,
913 )
923 )
914 coreconfigitem(
924 coreconfigitem(
915 b'experimental',
925 b'experimental',
916 b'bundlecompthreads.gzip',
926 b'bundlecompthreads.gzip',
917 default=None,
927 default=None,
918 )
928 )
919 coreconfigitem(
929 coreconfigitem(
920 b'experimental',
930 b'experimental',
921 b'bundlecompthreads.none',
931 b'bundlecompthreads.none',
922 default=None,
932 default=None,
923 )
933 )
924 coreconfigitem(
934 coreconfigitem(
925 b'experimental',
935 b'experimental',
926 b'bundlecompthreads.zstd',
936 b'bundlecompthreads.zstd',
927 default=None,
937 default=None,
928 )
938 )
929 coreconfigitem(
939 coreconfigitem(
930 b'experimental',
940 b'experimental',
931 b'changegroup3',
941 b'changegroup3',
932 default=False,
942 default=False,
933 )
943 )
934 coreconfigitem(
944 coreconfigitem(
935 b'experimental',
945 b'experimental',
936 b'changegroup4',
946 b'changegroup4',
937 default=False,
947 default=False,
938 )
948 )
939 coreconfigitem(
949 coreconfigitem(
940 b'experimental',
950 b'experimental',
941 b'cleanup-as-archived',
951 b'cleanup-as-archived',
942 default=False,
952 default=False,
943 )
953 )
944 coreconfigitem(
954 coreconfigitem(
945 b'experimental',
955 b'experimental',
946 b'clientcompressionengines',
956 b'clientcompressionengines',
947 default=list,
957 default=list,
948 )
958 )
949 coreconfigitem(
959 coreconfigitem(
950 b'experimental',
960 b'experimental',
951 b'copytrace',
961 b'copytrace',
952 default=b'on',
962 default=b'on',
953 )
963 )
954 coreconfigitem(
964 coreconfigitem(
955 b'experimental',
965 b'experimental',
956 b'copytrace.movecandidateslimit',
966 b'copytrace.movecandidateslimit',
957 default=100,
967 default=100,
958 )
968 )
959 coreconfigitem(
969 coreconfigitem(
960 b'experimental',
970 b'experimental',
961 b'copytrace.sourcecommitlimit',
971 b'copytrace.sourcecommitlimit',
962 default=100,
972 default=100,
963 )
973 )
964 coreconfigitem(
974 coreconfigitem(
965 b'experimental',
975 b'experimental',
966 b'copies.read-from',
976 b'copies.read-from',
967 default=b"filelog-only",
977 default=b"filelog-only",
968 )
978 )
969 coreconfigitem(
979 coreconfigitem(
970 b'experimental',
980 b'experimental',
971 b'copies.write-to',
981 b'copies.write-to',
972 default=b'filelog-only',
982 default=b'filelog-only',
973 )
983 )
974 coreconfigitem(
984 coreconfigitem(
975 b'experimental',
985 b'experimental',
976 b'crecordtest',
986 b'crecordtest',
977 default=None,
987 default=None,
978 )
988 )
979 coreconfigitem(
989 coreconfigitem(
980 b'experimental',
990 b'experimental',
981 b'directaccess',
991 b'directaccess',
982 default=False,
992 default=False,
983 )
993 )
984 coreconfigitem(
994 coreconfigitem(
985 b'experimental',
995 b'experimental',
986 b'directaccess.revnums',
996 b'directaccess.revnums',
987 default=False,
997 default=False,
988 )
998 )
989 coreconfigitem(
999 coreconfigitem(
990 b'experimental',
1000 b'experimental',
991 b'editortmpinhg',
1001 b'editortmpinhg',
992 default=False,
1002 default=False,
993 )
1003 )
994 coreconfigitem(
1004 coreconfigitem(
995 b'experimental',
1005 b'experimental',
996 b'evolution',
1006 b'evolution',
997 default=list,
1007 default=list,
998 )
1008 )
999 coreconfigitem(
1009 coreconfigitem(
1000 b'experimental',
1010 b'experimental',
1001 b'evolution.allowdivergence',
1011 b'evolution.allowdivergence',
1002 default=False,
1012 default=False,
1003 alias=[(b'experimental', b'allowdivergence')],
1013 alias=[(b'experimental', b'allowdivergence')],
1004 )
1014 )
1005 coreconfigitem(
1015 coreconfigitem(
1006 b'experimental',
1016 b'experimental',
1007 b'evolution.allowunstable',
1017 b'evolution.allowunstable',
1008 default=None,
1018 default=None,
1009 )
1019 )
1010 coreconfigitem(
1020 coreconfigitem(
1011 b'experimental',
1021 b'experimental',
1012 b'evolution.createmarkers',
1022 b'evolution.createmarkers',
1013 default=None,
1023 default=None,
1014 )
1024 )
1015 coreconfigitem(
1025 coreconfigitem(
1016 b'experimental',
1026 b'experimental',
1017 b'evolution.effect-flags',
1027 b'evolution.effect-flags',
1018 default=True,
1028 default=True,
1019 alias=[(b'experimental', b'effect-flags')],
1029 alias=[(b'experimental', b'effect-flags')],
1020 )
1030 )
1021 coreconfigitem(
1031 coreconfigitem(
1022 b'experimental',
1032 b'experimental',
1023 b'evolution.exchange',
1033 b'evolution.exchange',
1024 default=None,
1034 default=None,
1025 )
1035 )
1026 coreconfigitem(
1036 coreconfigitem(
1027 b'experimental',
1037 b'experimental',
1028 b'evolution.bundle-obsmarker',
1038 b'evolution.bundle-obsmarker',
1029 default=False,
1039 default=False,
1030 )
1040 )
1031 coreconfigitem(
1041 coreconfigitem(
1032 b'experimental',
1042 b'experimental',
1033 b'evolution.bundle-obsmarker:mandatory',
1043 b'evolution.bundle-obsmarker:mandatory',
1034 default=True,
1044 default=True,
1035 )
1045 )
1036 coreconfigitem(
1046 coreconfigitem(
1037 b'experimental',
1047 b'experimental',
1038 b'log.topo',
1048 b'log.topo',
1039 default=False,
1049 default=False,
1040 )
1050 )
1041 coreconfigitem(
1051 coreconfigitem(
1042 b'experimental',
1052 b'experimental',
1043 b'evolution.report-instabilities',
1053 b'evolution.report-instabilities',
1044 default=True,
1054 default=True,
1045 )
1055 )
1046 coreconfigitem(
1056 coreconfigitem(
1047 b'experimental',
1057 b'experimental',
1048 b'evolution.track-operation',
1058 b'evolution.track-operation',
1049 default=True,
1059 default=True,
1050 )
1060 )
1051 # repo-level config to exclude a revset visibility
1061 # repo-level config to exclude a revset visibility
1052 #
1062 #
1053 # The target use case is to use `share` to expose different subset of the same
1063 # The target use case is to use `share` to expose different subset of the same
1054 # repository, especially server side. See also `server.view`.
1064 # repository, especially server side. See also `server.view`.
1055 coreconfigitem(
1065 coreconfigitem(
1056 b'experimental',
1066 b'experimental',
1057 b'extra-filter-revs',
1067 b'extra-filter-revs',
1058 default=None,
1068 default=None,
1059 )
1069 )
1060 coreconfigitem(
1070 coreconfigitem(
1061 b'experimental',
1071 b'experimental',
1062 b'maxdeltachainspan',
1072 b'maxdeltachainspan',
1063 default=-1,
1073 default=-1,
1064 )
1074 )
1065 # tracks files which were undeleted (merge might delete them but we explicitly
1075 # tracks files which were undeleted (merge might delete them but we explicitly
1066 # kept/undeleted them) and creates new filenodes for them
1076 # kept/undeleted them) and creates new filenodes for them
1067 coreconfigitem(
1077 coreconfigitem(
1068 b'experimental',
1078 b'experimental',
1069 b'merge-track-salvaged',
1079 b'merge-track-salvaged',
1070 default=False,
1080 default=False,
1071 )
1081 )
1072 coreconfigitem(
1082 coreconfigitem(
1073 b'experimental',
1083 b'experimental',
1074 b'mmapindexthreshold',
1084 b'mmapindexthreshold',
1075 default=None,
1085 default=None,
1076 )
1086 )
1077 coreconfigitem(
1087 coreconfigitem(
1078 b'experimental',
1088 b'experimental',
1079 b'narrow',
1089 b'narrow',
1080 default=False,
1090 default=False,
1081 )
1091 )
1082 coreconfigitem(
1092 coreconfigitem(
1083 b'experimental',
1093 b'experimental',
1084 b'nonnormalparanoidcheck',
1094 b'nonnormalparanoidcheck',
1085 default=False,
1095 default=False,
1086 )
1096 )
1087 coreconfigitem(
1097 coreconfigitem(
1088 b'experimental',
1098 b'experimental',
1089 b'exportableenviron',
1099 b'exportableenviron',
1090 default=list,
1100 default=list,
1091 )
1101 )
1092 coreconfigitem(
1102 coreconfigitem(
1093 b'experimental',
1103 b'experimental',
1094 b'extendedheader.index',
1104 b'extendedheader.index',
1095 default=None,
1105 default=None,
1096 )
1106 )
1097 coreconfigitem(
1107 coreconfigitem(
1098 b'experimental',
1108 b'experimental',
1099 b'extendedheader.similarity',
1109 b'extendedheader.similarity',
1100 default=False,
1110 default=False,
1101 )
1111 )
1102 coreconfigitem(
1112 coreconfigitem(
1103 b'experimental',
1113 b'experimental',
1104 b'graphshorten',
1114 b'graphshorten',
1105 default=False,
1115 default=False,
1106 )
1116 )
1107 coreconfigitem(
1117 coreconfigitem(
1108 b'experimental',
1118 b'experimental',
1109 b'graphstyle.parent',
1119 b'graphstyle.parent',
1110 default=dynamicdefault,
1120 default=dynamicdefault,
1111 )
1121 )
1112 coreconfigitem(
1122 coreconfigitem(
1113 b'experimental',
1123 b'experimental',
1114 b'graphstyle.missing',
1124 b'graphstyle.missing',
1115 default=dynamicdefault,
1125 default=dynamicdefault,
1116 )
1126 )
1117 coreconfigitem(
1127 coreconfigitem(
1118 b'experimental',
1128 b'experimental',
1119 b'graphstyle.grandparent',
1129 b'graphstyle.grandparent',
1120 default=dynamicdefault,
1130 default=dynamicdefault,
1121 )
1131 )
1122 coreconfigitem(
1132 coreconfigitem(
1123 b'experimental',
1133 b'experimental',
1124 b'hook-track-tags',
1134 b'hook-track-tags',
1125 default=False,
1135 default=False,
1126 )
1136 )
1127 coreconfigitem(
1137 coreconfigitem(
1128 b'experimental',
1138 b'experimental',
1129 b'httppostargs',
1139 b'httppostargs',
1130 default=False,
1140 default=False,
1131 )
1141 )
1132 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1142 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1133 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1143 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1134
1144
1135 coreconfigitem(
1145 coreconfigitem(
1136 b'experimental',
1146 b'experimental',
1137 b'obsmarkers-exchange-debug',
1147 b'obsmarkers-exchange-debug',
1138 default=False,
1148 default=False,
1139 )
1149 )
1140 coreconfigitem(
1150 coreconfigitem(
1141 b'experimental',
1151 b'experimental',
1142 b'remotenames',
1152 b'remotenames',
1143 default=False,
1153 default=False,
1144 )
1154 )
1145 coreconfigitem(
1155 coreconfigitem(
1146 b'experimental',
1156 b'experimental',
1147 b'removeemptydirs',
1157 b'removeemptydirs',
1148 default=True,
1158 default=True,
1149 )
1159 )
1150 coreconfigitem(
1160 coreconfigitem(
1151 b'experimental',
1161 b'experimental',
1152 b'revert.interactive.select-to-keep',
1162 b'revert.interactive.select-to-keep',
1153 default=False,
1163 default=False,
1154 )
1164 )
1155 coreconfigitem(
1165 coreconfigitem(
1156 b'experimental',
1166 b'experimental',
1157 b'revisions.prefixhexnode',
1167 b'revisions.prefixhexnode',
1158 default=False,
1168 default=False,
1159 )
1169 )
1160 # "out of experimental" todo list.
1170 # "out of experimental" todo list.
1161 #
1171 #
1162 # * include management of a persistent nodemap in the main docket
1172 # * include management of a persistent nodemap in the main docket
1163 # * enforce a "no-truncate" policy for mmap safety
1173 # * enforce a "no-truncate" policy for mmap safety
1164 # - for censoring operation
1174 # - for censoring operation
1165 # - for stripping operation
1175 # - for stripping operation
1166 # - for rollback operation
1176 # - for rollback operation
1167 # * proper streaming (race free) of the docket file
1177 # * proper streaming (race free) of the docket file
1168 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1178 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1169 # * Exchange-wise, we will also need to do something more efficient than
1179 # * Exchange-wise, we will also need to do something more efficient than
1170 # keeping references to the affected revlogs, especially memory-wise when
1180 # keeping references to the affected revlogs, especially memory-wise when
1171 # rewriting sidedata.
1181 # rewriting sidedata.
1172 # * introduce a proper solution to reduce the number of filelog related files.
1182 # * introduce a proper solution to reduce the number of filelog related files.
1173 # * use caching for reading sidedata (similar to what we do for data).
1183 # * use caching for reading sidedata (similar to what we do for data).
1174 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1184 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1175 # * Improvement to consider
1185 # * Improvement to consider
1176 # - avoid compression header in chunk using the default compression?
1186 # - avoid compression header in chunk using the default compression?
1177 # - forbid "inline" compression mode entirely?
1187 # - forbid "inline" compression mode entirely?
1178 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1188 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1179 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1189 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1180 # - keep track of chain base or size (probably not that useful anymore)
1190 # - keep track of chain base or size (probably not that useful anymore)
1181 coreconfigitem(
1191 coreconfigitem(
1182 b'experimental',
1192 b'experimental',
1183 b'revlogv2',
1193 b'revlogv2',
1184 default=None,
1194 default=None,
1185 )
1195 )
1186 coreconfigitem(
1196 coreconfigitem(
1187 b'experimental',
1197 b'experimental',
1188 b'revisions.disambiguatewithin',
1198 b'revisions.disambiguatewithin',
1189 default=None,
1199 default=None,
1190 )
1200 )
1191 coreconfigitem(
1201 coreconfigitem(
1192 b'experimental',
1202 b'experimental',
1193 b'rust.index',
1203 b'rust.index',
1194 default=False,
1204 default=False,
1195 )
1205 )
1196 coreconfigitem(
1206 coreconfigitem(
1197 b'experimental',
1207 b'experimental',
1198 b'server.filesdata.recommended-batch-size',
1208 b'server.filesdata.recommended-batch-size',
1199 default=50000,
1209 default=50000,
1200 )
1210 )
1201 coreconfigitem(
1211 coreconfigitem(
1202 b'experimental',
1212 b'experimental',
1203 b'server.manifestdata.recommended-batch-size',
1213 b'server.manifestdata.recommended-batch-size',
1204 default=100000,
1214 default=100000,
1205 )
1215 )
1206 coreconfigitem(
1216 coreconfigitem(
1207 b'experimental',
1217 b'experimental',
1208 b'server.stream-narrow-clones',
1218 b'server.stream-narrow-clones',
1209 default=False,
1219 default=False,
1210 )
1220 )
1211 coreconfigitem(
1221 coreconfigitem(
1212 b'experimental',
1222 b'experimental',
1213 b'single-head-per-branch',
1223 b'single-head-per-branch',
1214 default=False,
1224 default=False,
1215 )
1225 )
1216 coreconfigitem(
1226 coreconfigitem(
1217 b'experimental',
1227 b'experimental',
1218 b'single-head-per-branch:account-closed-heads',
1228 b'single-head-per-branch:account-closed-heads',
1219 default=False,
1229 default=False,
1220 )
1230 )
1221 coreconfigitem(
1231 coreconfigitem(
1222 b'experimental',
1232 b'experimental',
1223 b'single-head-per-branch:public-changes-only',
1233 b'single-head-per-branch:public-changes-only',
1224 default=False,
1234 default=False,
1225 )
1235 )
1226 coreconfigitem(
1236 coreconfigitem(
1227 b'experimental',
1237 b'experimental',
1228 b'sparse-read',
1238 b'sparse-read',
1229 default=False,
1239 default=False,
1230 )
1240 )
1231 coreconfigitem(
1241 coreconfigitem(
1232 b'experimental',
1242 b'experimental',
1233 b'sparse-read.density-threshold',
1243 b'sparse-read.density-threshold',
1234 default=0.50,
1244 default=0.50,
1235 )
1245 )
1236 coreconfigitem(
1246 coreconfigitem(
1237 b'experimental',
1247 b'experimental',
1238 b'sparse-read.min-gap-size',
1248 b'sparse-read.min-gap-size',
1239 default=b'65K',
1249 default=b'65K',
1240 )
1250 )
1241 coreconfigitem(
1251 coreconfigitem(
1242 b'experimental',
1252 b'experimental',
1243 b'treemanifest',
1253 b'treemanifest',
1244 default=False,
1254 default=False,
1245 )
1255 )
1246 coreconfigitem(
1256 coreconfigitem(
1247 b'experimental',
1257 b'experimental',
1248 b'update.atomic-file',
1258 b'update.atomic-file',
1249 default=False,
1259 default=False,
1250 )
1260 )
1251 coreconfigitem(
1261 coreconfigitem(
1252 b'experimental',
1262 b'experimental',
1253 b'web.full-garbage-collection-rate',
1263 b'web.full-garbage-collection-rate',
1254 default=1, # still forcing a full collection on each request
1264 default=1, # still forcing a full collection on each request
1255 )
1265 )
1256 coreconfigitem(
1266 coreconfigitem(
1257 b'experimental',
1267 b'experimental',
1258 b'worker.wdir-get-thread-safe',
1268 b'worker.wdir-get-thread-safe',
1259 default=False,
1269 default=False,
1260 )
1270 )
1261 coreconfigitem(
1271 coreconfigitem(
1262 b'experimental',
1272 b'experimental',
1263 b'worker.repository-upgrade',
1273 b'worker.repository-upgrade',
1264 default=False,
1274 default=False,
1265 )
1275 )
1266 coreconfigitem(
1276 coreconfigitem(
1267 b'experimental',
1277 b'experimental',
1268 b'xdiff',
1278 b'xdiff',
1269 default=False,
1279 default=False,
1270 )
1280 )
1271 coreconfigitem(
1281 coreconfigitem(
1272 b'extensions',
1282 b'extensions',
1273 b'[^:]*',
1283 b'[^:]*',
1274 default=None,
1284 default=None,
1275 generic=True,
1285 generic=True,
1276 )
1286 )
1277 coreconfigitem(
1287 coreconfigitem(
1278 b'extensions',
1288 b'extensions',
1279 b'[^:]*:required',
1289 b'[^:]*:required',
1280 default=False,
1290 default=False,
1281 generic=True,
1291 generic=True,
1282 )
1292 )
1283 coreconfigitem(
1293 coreconfigitem(
1284 b'extdata',
1294 b'extdata',
1285 b'.*',
1295 b'.*',
1286 default=None,
1296 default=None,
1287 generic=True,
1297 generic=True,
1288 )
1298 )
1289 coreconfigitem(
1299 coreconfigitem(
1290 b'format',
1300 b'format',
1291 b'bookmarks-in-store',
1301 b'bookmarks-in-store',
1292 default=False,
1302 default=False,
1293 )
1303 )
1294 coreconfigitem(
1304 coreconfigitem(
1295 b'format',
1305 b'format',
1296 b'chunkcachesize',
1306 b'chunkcachesize',
1297 default=None,
1307 default=None,
1298 experimental=True,
1308 experimental=True,
1299 )
1309 )
1300 coreconfigitem(
1310 coreconfigitem(
1301 # Enable this dirstate format *when creating a new repository*.
1311 # Enable this dirstate format *when creating a new repository*.
1302 # Which format to use for existing repos is controlled by .hg/requires
1312 # Which format to use for existing repos is controlled by .hg/requires
1303 b'format',
1313 b'format',
1304 b'use-dirstate-v2',
1314 b'use-dirstate-v2',
1305 default=False,
1315 default=False,
1306 experimental=True,
1316 experimental=True,
1307 alias=[(b'format', b'exp-rc-dirstate-v2')],
1317 alias=[(b'format', b'exp-rc-dirstate-v2')],
1308 )
1318 )
1309 coreconfigitem(
1319 coreconfigitem(
1310 b'format',
1320 b'format',
1311 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
1321 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
1312 default=False,
1322 default=False,
1313 experimental=True,
1323 experimental=True,
1314 )
1324 )
1315 coreconfigitem(
1325 coreconfigitem(
1316 b'format',
1326 b'format',
1317 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
1327 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
1318 default=False,
1328 default=False,
1319 experimental=True,
1329 experimental=True,
1320 )
1330 )
1321 coreconfigitem(
1331 coreconfigitem(
1322 b'format',
1332 b'format',
1323 b'use-dirstate-tracked-hint',
1333 b'use-dirstate-tracked-hint',
1324 default=False,
1334 default=False,
1325 experimental=True,
1335 experimental=True,
1326 )
1336 )
1327 coreconfigitem(
1337 coreconfigitem(
1328 b'format',
1338 b'format',
1329 b'use-dirstate-tracked-hint.version',
1339 b'use-dirstate-tracked-hint.version',
1330 default=1,
1340 default=1,
1331 experimental=True,
1341 experimental=True,
1332 )
1342 )
1333 coreconfigitem(
1343 coreconfigitem(
1334 b'format',
1344 b'format',
1335 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
1345 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
1336 default=False,
1346 default=False,
1337 experimental=True,
1347 experimental=True,
1338 )
1348 )
1339 coreconfigitem(
1349 coreconfigitem(
1340 b'format',
1350 b'format',
1341 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
1351 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
1342 default=False,
1352 default=False,
1343 experimental=True,
1353 experimental=True,
1344 )
1354 )
1345 coreconfigitem(
1355 coreconfigitem(
1346 b'format',
1356 b'format',
1347 b'dotencode',
1357 b'dotencode',
1348 default=True,
1358 default=True,
1349 )
1359 )
1350 coreconfigitem(
1360 coreconfigitem(
1351 b'format',
1361 b'format',
1352 b'generaldelta',
1362 b'generaldelta',
1353 default=False,
1363 default=False,
1354 experimental=True,
1364 experimental=True,
1355 )
1365 )
1356 coreconfigitem(
1366 coreconfigitem(
1357 b'format',
1367 b'format',
1358 b'manifestcachesize',
1368 b'manifestcachesize',
1359 default=None,
1369 default=None,
1360 experimental=True,
1370 experimental=True,
1361 )
1371 )
1362 coreconfigitem(
1372 coreconfigitem(
1363 b'format',
1373 b'format',
1364 b'maxchainlen',
1374 b'maxchainlen',
1365 default=dynamicdefault,
1375 default=dynamicdefault,
1366 experimental=True,
1376 experimental=True,
1367 )
1377 )
1368 coreconfigitem(
1378 coreconfigitem(
1369 b'format',
1379 b'format',
1370 b'obsstore-version',
1380 b'obsstore-version',
1371 default=None,
1381 default=None,
1372 )
1382 )
1373 coreconfigitem(
1383 coreconfigitem(
1374 b'format',
1384 b'format',
1375 b'sparse-revlog',
1385 b'sparse-revlog',
1376 default=True,
1386 default=True,
1377 )
1387 )
1378 coreconfigitem(
1388 coreconfigitem(
1379 b'format',
1389 b'format',
1380 b'revlog-compression',
1390 b'revlog-compression',
1381 default=lambda: [b'zstd', b'zlib'],
1391 default=lambda: [b'zstd', b'zlib'],
1382 alias=[(b'experimental', b'format.compression')],
1392 alias=[(b'experimental', b'format.compression')],
1383 )
1393 )
1384 # Experimental TODOs:
1394 # Experimental TODOs:
1385 #
1395 #
1386 # * Same as for revlogv2 (but for the reduction of the number of files)
1396 # * Same as for revlogv2 (but for the reduction of the number of files)
1387 # * Actually computing the rank of changesets
1397 # * Actually computing the rank of changesets
1388 # * Improvement to investigate
1398 # * Improvement to investigate
1389 # - storing .hgtags fnode
1399 # - storing .hgtags fnode
1390 # - storing branch related identifier
1400 # - storing branch related identifier
1391
1401
1392 coreconfigitem(
1402 coreconfigitem(
1393 b'format',
1403 b'format',
1394 b'exp-use-changelog-v2',
1404 b'exp-use-changelog-v2',
1395 default=None,
1405 default=None,
1396 experimental=True,
1406 experimental=True,
1397 )
1407 )
1398 coreconfigitem(
1408 coreconfigitem(
1399 b'format',
1409 b'format',
1400 b'usefncache',
1410 b'usefncache',
1401 default=True,
1411 default=True,
1402 )
1412 )
1403 coreconfigitem(
1413 coreconfigitem(
1404 b'format',
1414 b'format',
1405 b'usegeneraldelta',
1415 b'usegeneraldelta',
1406 default=True,
1416 default=True,
1407 )
1417 )
1408 coreconfigitem(
1418 coreconfigitem(
1409 b'format',
1419 b'format',
1410 b'usestore',
1420 b'usestore',
1411 default=True,
1421 default=True,
1412 )
1422 )
1413
1423
1414
1424
1415 def _persistent_nodemap_default():
1425 def _persistent_nodemap_default():
1416 """compute `use-persistent-nodemap` default value
1426 """compute `use-persistent-nodemap` default value
1417
1427
1418 The feature is disabled unless a fast implementation is available.
1428 The feature is disabled unless a fast implementation is available.
1419 """
1429 """
1420 from . import policy
1430 from . import policy
1421
1431
1422 return policy.importrust('revlog') is not None
1432 return policy.importrust('revlog') is not None
1423
1433
1424
1434
1425 coreconfigitem(
1435 coreconfigitem(
1426 b'format',
1436 b'format',
1427 b'use-persistent-nodemap',
1437 b'use-persistent-nodemap',
1428 default=_persistent_nodemap_default,
1438 default=_persistent_nodemap_default,
1429 )
1439 )
1430 coreconfigitem(
1440 coreconfigitem(
1431 b'format',
1441 b'format',
1432 b'exp-use-copies-side-data-changeset',
1442 b'exp-use-copies-side-data-changeset',
1433 default=False,
1443 default=False,
1434 experimental=True,
1444 experimental=True,
1435 )
1445 )
1436 coreconfigitem(
1446 coreconfigitem(
1437 b'format',
1447 b'format',
1438 b'use-share-safe',
1448 b'use-share-safe',
1439 default=True,
1449 default=True,
1440 )
1450 )
1441 coreconfigitem(
1451 coreconfigitem(
1442 b'format',
1452 b'format',
1443 b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
1453 b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
1444 default=False,
1454 default=False,
1445 experimental=True,
1455 experimental=True,
1446 )
1456 )
1447 coreconfigitem(
1457 coreconfigitem(
1448 b'format',
1458 b'format',
1449 b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
1459 b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
1450 default=False,
1460 default=False,
1451 experimental=True,
1461 experimental=True,
1452 )
1462 )
1453
1463
1454 # Moving this on by default means we are confident about the scaling of phases.
1464 # Moving this on by default means we are confident about the scaling of phases.
1455 # This is not garanteed to be the case at the time this message is written.
1465 # This is not garanteed to be the case at the time this message is written.
1456 coreconfigitem(
1466 coreconfigitem(
1457 b'format',
1467 b'format',
1458 b'use-internal-phase',
1468 b'use-internal-phase',
1459 default=False,
1469 default=False,
1460 experimental=True,
1470 experimental=True,
1461 )
1471 )
1462 # The interaction between the archived phase and obsolescence markers needs to
1472 # The interaction between the archived phase and obsolescence markers needs to
1463 # be sorted out before wider usage of this are to be considered.
1473 # be sorted out before wider usage of this are to be considered.
1464 #
1474 #
1465 # At the time this message is written, behavior when archiving obsolete
1475 # At the time this message is written, behavior when archiving obsolete
1466 # changeset differ significantly from stripping. As part of stripping, we also
1476 # changeset differ significantly from stripping. As part of stripping, we also
1467 # remove the obsolescence marker associated to the stripped changesets,
1477 # remove the obsolescence marker associated to the stripped changesets,
1468 # revealing the precedecessors changesets when applicable. When archiving, we
1478 # revealing the precedecessors changesets when applicable. When archiving, we
1469 # don't touch the obsolescence markers, keeping everything hidden. This can
1479 # don't touch the obsolescence markers, keeping everything hidden. This can
1470 # result in quite confusing situation for people combining exchanging draft
1480 # result in quite confusing situation for people combining exchanging draft
1471 # with the archived phases. As some markers needed by others may be skipped
1481 # with the archived phases. As some markers needed by others may be skipped
1472 # during exchange.
1482 # during exchange.
1473 coreconfigitem(
1483 coreconfigitem(
1474 b'format',
1484 b'format',
1475 b'exp-archived-phase',
1485 b'exp-archived-phase',
1476 default=False,
1486 default=False,
1477 experimental=True,
1487 experimental=True,
1478 )
1488 )
1479 coreconfigitem(
1489 coreconfigitem(
1480 b'shelve',
1490 b'shelve',
1481 b'store',
1491 b'store',
1482 default=b'internal',
1492 default=b'internal',
1483 experimental=True,
1493 experimental=True,
1484 )
1494 )
1485 coreconfigitem(
1495 coreconfigitem(
1486 b'fsmonitor',
1496 b'fsmonitor',
1487 b'warn_when_unused',
1497 b'warn_when_unused',
1488 default=True,
1498 default=True,
1489 )
1499 )
1490 coreconfigitem(
1500 coreconfigitem(
1491 b'fsmonitor',
1501 b'fsmonitor',
1492 b'warn_update_file_count',
1502 b'warn_update_file_count',
1493 default=50000,
1503 default=50000,
1494 )
1504 )
1495 coreconfigitem(
1505 coreconfigitem(
1496 b'fsmonitor',
1506 b'fsmonitor',
1497 b'warn_update_file_count_rust',
1507 b'warn_update_file_count_rust',
1498 default=400000,
1508 default=400000,
1499 )
1509 )
1500 coreconfigitem(
1510 coreconfigitem(
1501 b'help',
1511 b'help',
1502 br'hidden-command\..*',
1512 br'hidden-command\..*',
1503 default=False,
1513 default=False,
1504 generic=True,
1514 generic=True,
1505 )
1515 )
1506 coreconfigitem(
1516 coreconfigitem(
1507 b'help',
1517 b'help',
1508 br'hidden-topic\..*',
1518 br'hidden-topic\..*',
1509 default=False,
1519 default=False,
1510 generic=True,
1520 generic=True,
1511 )
1521 )
1512 coreconfigitem(
1522 coreconfigitem(
1513 b'hooks',
1523 b'hooks',
1514 b'[^:]*',
1524 b'[^:]*',
1515 default=dynamicdefault,
1525 default=dynamicdefault,
1516 generic=True,
1526 generic=True,
1517 )
1527 )
1518 coreconfigitem(
1528 coreconfigitem(
1519 b'hooks',
1529 b'hooks',
1520 b'.*:run-with-plain',
1530 b'.*:run-with-plain',
1521 default=True,
1531 default=True,
1522 generic=True,
1532 generic=True,
1523 )
1533 )
1524 coreconfigitem(
1534 coreconfigitem(
1525 b'hgweb-paths',
1535 b'hgweb-paths',
1526 b'.*',
1536 b'.*',
1527 default=list,
1537 default=list,
1528 generic=True,
1538 generic=True,
1529 )
1539 )
1530 coreconfigitem(
1540 coreconfigitem(
1531 b'hostfingerprints',
1541 b'hostfingerprints',
1532 b'.*',
1542 b'.*',
1533 default=list,
1543 default=list,
1534 generic=True,
1544 generic=True,
1535 )
1545 )
1536 coreconfigitem(
1546 coreconfigitem(
1537 b'hostsecurity',
1547 b'hostsecurity',
1538 b'ciphers',
1548 b'ciphers',
1539 default=None,
1549 default=None,
1540 )
1550 )
1541 coreconfigitem(
1551 coreconfigitem(
1542 b'hostsecurity',
1552 b'hostsecurity',
1543 b'minimumprotocol',
1553 b'minimumprotocol',
1544 default=dynamicdefault,
1554 default=dynamicdefault,
1545 )
1555 )
1546 coreconfigitem(
1556 coreconfigitem(
1547 b'hostsecurity',
1557 b'hostsecurity',
1548 b'.*:minimumprotocol$',
1558 b'.*:minimumprotocol$',
1549 default=dynamicdefault,
1559 default=dynamicdefault,
1550 generic=True,
1560 generic=True,
1551 )
1561 )
1552 coreconfigitem(
1562 coreconfigitem(
1553 b'hostsecurity',
1563 b'hostsecurity',
1554 b'.*:ciphers$',
1564 b'.*:ciphers$',
1555 default=dynamicdefault,
1565 default=dynamicdefault,
1556 generic=True,
1566 generic=True,
1557 )
1567 )
1558 coreconfigitem(
1568 coreconfigitem(
1559 b'hostsecurity',
1569 b'hostsecurity',
1560 b'.*:fingerprints$',
1570 b'.*:fingerprints$',
1561 default=list,
1571 default=list,
1562 generic=True,
1572 generic=True,
1563 )
1573 )
1564 coreconfigitem(
1574 coreconfigitem(
1565 b'hostsecurity',
1575 b'hostsecurity',
1566 b'.*:verifycertsfile$',
1576 b'.*:verifycertsfile$',
1567 default=None,
1577 default=None,
1568 generic=True,
1578 generic=True,
1569 )
1579 )
1570
1580
1571 coreconfigitem(
1581 coreconfigitem(
1572 b'http_proxy',
1582 b'http_proxy',
1573 b'always',
1583 b'always',
1574 default=False,
1584 default=False,
1575 )
1585 )
1576 coreconfigitem(
1586 coreconfigitem(
1577 b'http_proxy',
1587 b'http_proxy',
1578 b'host',
1588 b'host',
1579 default=None,
1589 default=None,
1580 )
1590 )
1581 coreconfigitem(
1591 coreconfigitem(
1582 b'http_proxy',
1592 b'http_proxy',
1583 b'no',
1593 b'no',
1584 default=list,
1594 default=list,
1585 )
1595 )
1586 coreconfigitem(
1596 coreconfigitem(
1587 b'http_proxy',
1597 b'http_proxy',
1588 b'passwd',
1598 b'passwd',
1589 default=None,
1599 default=None,
1590 )
1600 )
1591 coreconfigitem(
1601 coreconfigitem(
1592 b'http_proxy',
1602 b'http_proxy',
1593 b'user',
1603 b'user',
1594 default=None,
1604 default=None,
1595 )
1605 )
1596
1606
1597 coreconfigitem(
1607 coreconfigitem(
1598 b'http',
1608 b'http',
1599 b'timeout',
1609 b'timeout',
1600 default=None,
1610 default=None,
1601 )
1611 )
1602
1612
1603 coreconfigitem(
1613 coreconfigitem(
1604 b'logtoprocess',
1614 b'logtoprocess',
1605 b'commandexception',
1615 b'commandexception',
1606 default=None,
1616 default=None,
1607 )
1617 )
1608 coreconfigitem(
1618 coreconfigitem(
1609 b'logtoprocess',
1619 b'logtoprocess',
1610 b'commandfinish',
1620 b'commandfinish',
1611 default=None,
1621 default=None,
1612 )
1622 )
1613 coreconfigitem(
1623 coreconfigitem(
1614 b'logtoprocess',
1624 b'logtoprocess',
1615 b'command',
1625 b'command',
1616 default=None,
1626 default=None,
1617 )
1627 )
1618 coreconfigitem(
1628 coreconfigitem(
1619 b'logtoprocess',
1629 b'logtoprocess',
1620 b'develwarn',
1630 b'develwarn',
1621 default=None,
1631 default=None,
1622 )
1632 )
1623 coreconfigitem(
1633 coreconfigitem(
1624 b'logtoprocess',
1634 b'logtoprocess',
1625 b'uiblocked',
1635 b'uiblocked',
1626 default=None,
1636 default=None,
1627 )
1637 )
1628 coreconfigitem(
1638 coreconfigitem(
1629 b'merge',
1639 b'merge',
1630 b'checkunknown',
1640 b'checkunknown',
1631 default=b'abort',
1641 default=b'abort',
1632 )
1642 )
1633 coreconfigitem(
1643 coreconfigitem(
1634 b'merge',
1644 b'merge',
1635 b'checkignored',
1645 b'checkignored',
1636 default=b'abort',
1646 default=b'abort',
1637 )
1647 )
1638 coreconfigitem(
1648 coreconfigitem(
1639 b'experimental',
1649 b'experimental',
1640 b'merge.checkpathconflicts',
1650 b'merge.checkpathconflicts',
1641 default=False,
1651 default=False,
1642 )
1652 )
1643 coreconfigitem(
1653 coreconfigitem(
1644 b'merge',
1654 b'merge',
1645 b'followcopies',
1655 b'followcopies',
1646 default=True,
1656 default=True,
1647 )
1657 )
1648 coreconfigitem(
1658 coreconfigitem(
1649 b'merge',
1659 b'merge',
1650 b'on-failure',
1660 b'on-failure',
1651 default=b'continue',
1661 default=b'continue',
1652 )
1662 )
1653 coreconfigitem(
1663 coreconfigitem(
1654 b'merge',
1664 b'merge',
1655 b'preferancestor',
1665 b'preferancestor',
1656 default=lambda: [b'*'],
1666 default=lambda: [b'*'],
1657 experimental=True,
1667 experimental=True,
1658 )
1668 )
1659 coreconfigitem(
1669 coreconfigitem(
1660 b'merge',
1670 b'merge',
1661 b'strict-capability-check',
1671 b'strict-capability-check',
1662 default=False,
1672 default=False,
1663 )
1673 )
1664 coreconfigitem(
1674 coreconfigitem(
1665 b'merge',
1675 b'merge',
1666 b'disable-partial-tools',
1676 b'disable-partial-tools',
1667 default=False,
1677 default=False,
1668 experimental=True,
1678 experimental=True,
1669 )
1679 )
1670 coreconfigitem(
1680 coreconfigitem(
1671 b'partial-merge-tools',
1681 b'partial-merge-tools',
1672 b'.*',
1682 b'.*',
1673 default=None,
1683 default=None,
1674 generic=True,
1684 generic=True,
1675 experimental=True,
1685 experimental=True,
1676 )
1686 )
1677 coreconfigitem(
1687 coreconfigitem(
1678 b'partial-merge-tools',
1688 b'partial-merge-tools',
1679 br'.*\.patterns',
1689 br'.*\.patterns',
1680 default=dynamicdefault,
1690 default=dynamicdefault,
1681 generic=True,
1691 generic=True,
1682 priority=-1,
1692 priority=-1,
1683 experimental=True,
1693 experimental=True,
1684 )
1694 )
1685 coreconfigitem(
1695 coreconfigitem(
1686 b'partial-merge-tools',
1696 b'partial-merge-tools',
1687 br'.*\.executable$',
1697 br'.*\.executable$',
1688 default=dynamicdefault,
1698 default=dynamicdefault,
1689 generic=True,
1699 generic=True,
1690 priority=-1,
1700 priority=-1,
1691 experimental=True,
1701 experimental=True,
1692 )
1702 )
1693 coreconfigitem(
1703 coreconfigitem(
1694 b'partial-merge-tools',
1704 b'partial-merge-tools',
1695 br'.*\.order',
1705 br'.*\.order',
1696 default=0,
1706 default=0,
1697 generic=True,
1707 generic=True,
1698 priority=-1,
1708 priority=-1,
1699 experimental=True,
1709 experimental=True,
1700 )
1710 )
1701 coreconfigitem(
1711 coreconfigitem(
1702 b'partial-merge-tools',
1712 b'partial-merge-tools',
1703 br'.*\.args',
1713 br'.*\.args',
1704 default=b"$local $base $other",
1714 default=b"$local $base $other",
1705 generic=True,
1715 generic=True,
1706 priority=-1,
1716 priority=-1,
1707 experimental=True,
1717 experimental=True,
1708 )
1718 )
1709 coreconfigitem(
1719 coreconfigitem(
1710 b'partial-merge-tools',
1720 b'partial-merge-tools',
1711 br'.*\.disable',
1721 br'.*\.disable',
1712 default=False,
1722 default=False,
1713 generic=True,
1723 generic=True,
1714 priority=-1,
1724 priority=-1,
1715 experimental=True,
1725 experimental=True,
1716 )
1726 )
1717 coreconfigitem(
1727 coreconfigitem(
1718 b'merge-tools',
1728 b'merge-tools',
1719 b'.*',
1729 b'.*',
1720 default=None,
1730 default=None,
1721 generic=True,
1731 generic=True,
1722 )
1732 )
1723 coreconfigitem(
1733 coreconfigitem(
1724 b'merge-tools',
1734 b'merge-tools',
1725 br'.*\.args$',
1735 br'.*\.args$',
1726 default=b"$local $base $other",
1736 default=b"$local $base $other",
1727 generic=True,
1737 generic=True,
1728 priority=-1,
1738 priority=-1,
1729 )
1739 )
1730 coreconfigitem(
1740 coreconfigitem(
1731 b'merge-tools',
1741 b'merge-tools',
1732 br'.*\.binary$',
1742 br'.*\.binary$',
1733 default=False,
1743 default=False,
1734 generic=True,
1744 generic=True,
1735 priority=-1,
1745 priority=-1,
1736 )
1746 )
1737 coreconfigitem(
1747 coreconfigitem(
1738 b'merge-tools',
1748 b'merge-tools',
1739 br'.*\.check$',
1749 br'.*\.check$',
1740 default=list,
1750 default=list,
1741 generic=True,
1751 generic=True,
1742 priority=-1,
1752 priority=-1,
1743 )
1753 )
1744 coreconfigitem(
1754 coreconfigitem(
1745 b'merge-tools',
1755 b'merge-tools',
1746 br'.*\.checkchanged$',
1756 br'.*\.checkchanged$',
1747 default=False,
1757 default=False,
1748 generic=True,
1758 generic=True,
1749 priority=-1,
1759 priority=-1,
1750 )
1760 )
1751 coreconfigitem(
1761 coreconfigitem(
1752 b'merge-tools',
1762 b'merge-tools',
1753 br'.*\.executable$',
1763 br'.*\.executable$',
1754 default=dynamicdefault,
1764 default=dynamicdefault,
1755 generic=True,
1765 generic=True,
1756 priority=-1,
1766 priority=-1,
1757 )
1767 )
1758 coreconfigitem(
1768 coreconfigitem(
1759 b'merge-tools',
1769 b'merge-tools',
1760 br'.*\.fixeol$',
1770 br'.*\.fixeol$',
1761 default=False,
1771 default=False,
1762 generic=True,
1772 generic=True,
1763 priority=-1,
1773 priority=-1,
1764 )
1774 )
1765 coreconfigitem(
1775 coreconfigitem(
1766 b'merge-tools',
1776 b'merge-tools',
1767 br'.*\.gui$',
1777 br'.*\.gui$',
1768 default=False,
1778 default=False,
1769 generic=True,
1779 generic=True,
1770 priority=-1,
1780 priority=-1,
1771 )
1781 )
1772 coreconfigitem(
1782 coreconfigitem(
1773 b'merge-tools',
1783 b'merge-tools',
1774 br'.*\.mergemarkers$',
1784 br'.*\.mergemarkers$',
1775 default=b'basic',
1785 default=b'basic',
1776 generic=True,
1786 generic=True,
1777 priority=-1,
1787 priority=-1,
1778 )
1788 )
1779 coreconfigitem(
1789 coreconfigitem(
1780 b'merge-tools',
1790 b'merge-tools',
1781 br'.*\.mergemarkertemplate$',
1791 br'.*\.mergemarkertemplate$',
1782 default=dynamicdefault, # take from command-templates.mergemarker
1792 default=dynamicdefault, # take from command-templates.mergemarker
1783 generic=True,
1793 generic=True,
1784 priority=-1,
1794 priority=-1,
1785 )
1795 )
1786 coreconfigitem(
1796 coreconfigitem(
1787 b'merge-tools',
1797 b'merge-tools',
1788 br'.*\.priority$',
1798 br'.*\.priority$',
1789 default=0,
1799 default=0,
1790 generic=True,
1800 generic=True,
1791 priority=-1,
1801 priority=-1,
1792 )
1802 )
1793 coreconfigitem(
1803 coreconfigitem(
1794 b'merge-tools',
1804 b'merge-tools',
1795 br'.*\.premerge$',
1805 br'.*\.premerge$',
1796 default=dynamicdefault,
1806 default=dynamicdefault,
1797 generic=True,
1807 generic=True,
1798 priority=-1,
1808 priority=-1,
1799 )
1809 )
1800 coreconfigitem(
1810 coreconfigitem(
1801 b'merge-tools',
1811 b'merge-tools',
1802 br'.*\.symlink$',
1812 br'.*\.symlink$',
1803 default=False,
1813 default=False,
1804 generic=True,
1814 generic=True,
1805 priority=-1,
1815 priority=-1,
1806 )
1816 )
1807 coreconfigitem(
1817 coreconfigitem(
1808 b'pager',
1818 b'pager',
1809 b'attend-.*',
1819 b'attend-.*',
1810 default=dynamicdefault,
1820 default=dynamicdefault,
1811 generic=True,
1821 generic=True,
1812 )
1822 )
1813 coreconfigitem(
1823 coreconfigitem(
1814 b'pager',
1824 b'pager',
1815 b'ignore',
1825 b'ignore',
1816 default=list,
1826 default=list,
1817 )
1827 )
1818 coreconfigitem(
1828 coreconfigitem(
1819 b'pager',
1829 b'pager',
1820 b'pager',
1830 b'pager',
1821 default=dynamicdefault,
1831 default=dynamicdefault,
1822 )
1832 )
1823 coreconfigitem(
1833 coreconfigitem(
1824 b'patch',
1834 b'patch',
1825 b'eol',
1835 b'eol',
1826 default=b'strict',
1836 default=b'strict',
1827 )
1837 )
1828 coreconfigitem(
1838 coreconfigitem(
1829 b'patch',
1839 b'patch',
1830 b'fuzz',
1840 b'fuzz',
1831 default=2,
1841 default=2,
1832 )
1842 )
1833 coreconfigitem(
1843 coreconfigitem(
1834 b'paths',
1844 b'paths',
1835 b'default',
1845 b'default',
1836 default=None,
1846 default=None,
1837 )
1847 )
1838 coreconfigitem(
1848 coreconfigitem(
1839 b'paths',
1849 b'paths',
1840 b'default-push',
1850 b'default-push',
1841 default=None,
1851 default=None,
1842 )
1852 )
1843 coreconfigitem(
1853 coreconfigitem(
1844 b'paths',
1854 b'paths',
1845 b'.*',
1855 b'.*',
1846 default=None,
1856 default=None,
1847 generic=True,
1857 generic=True,
1848 )
1858 )
1849 coreconfigitem(
1859 coreconfigitem(
1850 b'paths',
1860 b'paths',
1851 b'.*:bookmarks.mode',
1861 b'.*:bookmarks.mode',
1852 default='default',
1862 default='default',
1853 generic=True,
1863 generic=True,
1854 )
1864 )
1855 coreconfigitem(
1865 coreconfigitem(
1856 b'paths',
1866 b'paths',
1857 b'.*:multi-urls',
1867 b'.*:multi-urls',
1858 default=False,
1868 default=False,
1859 generic=True,
1869 generic=True,
1860 )
1870 )
1861 coreconfigitem(
1871 coreconfigitem(
1862 b'paths',
1872 b'paths',
1863 b'.*:pushrev',
1873 b'.*:pushrev',
1864 default=None,
1874 default=None,
1865 generic=True,
1875 generic=True,
1866 )
1876 )
1867 coreconfigitem(
1877 coreconfigitem(
1868 b'paths',
1878 b'paths',
1869 b'.*:pushurl',
1879 b'.*:pushurl',
1870 default=None,
1880 default=None,
1871 generic=True,
1881 generic=True,
1872 )
1882 )
1873 coreconfigitem(
1883 coreconfigitem(
1874 b'phases',
1884 b'phases',
1875 b'checksubrepos',
1885 b'checksubrepos',
1876 default=b'follow',
1886 default=b'follow',
1877 )
1887 )
1878 coreconfigitem(
1888 coreconfigitem(
1879 b'phases',
1889 b'phases',
1880 b'new-commit',
1890 b'new-commit',
1881 default=b'draft',
1891 default=b'draft',
1882 )
1892 )
1883 coreconfigitem(
1893 coreconfigitem(
1884 b'phases',
1894 b'phases',
1885 b'publish',
1895 b'publish',
1886 default=True,
1896 default=True,
1887 )
1897 )
1888 coreconfigitem(
1898 coreconfigitem(
1889 b'profiling',
1899 b'profiling',
1890 b'enabled',
1900 b'enabled',
1891 default=False,
1901 default=False,
1892 )
1902 )
1893 coreconfigitem(
1903 coreconfigitem(
1894 b'profiling',
1904 b'profiling',
1895 b'format',
1905 b'format',
1896 default=b'text',
1906 default=b'text',
1897 )
1907 )
1898 coreconfigitem(
1908 coreconfigitem(
1899 b'profiling',
1909 b'profiling',
1900 b'freq',
1910 b'freq',
1901 default=1000,
1911 default=1000,
1902 )
1912 )
1903 coreconfigitem(
1913 coreconfigitem(
1904 b'profiling',
1914 b'profiling',
1905 b'limit',
1915 b'limit',
1906 default=30,
1916 default=30,
1907 )
1917 )
1908 coreconfigitem(
1918 coreconfigitem(
1909 b'profiling',
1919 b'profiling',
1910 b'nested',
1920 b'nested',
1911 default=0,
1921 default=0,
1912 )
1922 )
1913 coreconfigitem(
1923 coreconfigitem(
1914 b'profiling',
1924 b'profiling',
1915 b'output',
1925 b'output',
1916 default=None,
1926 default=None,
1917 )
1927 )
1918 coreconfigitem(
1928 coreconfigitem(
1919 b'profiling',
1929 b'profiling',
1920 b'showmax',
1930 b'showmax',
1921 default=0.999,
1931 default=0.999,
1922 )
1932 )
1923 coreconfigitem(
1933 coreconfigitem(
1924 b'profiling',
1934 b'profiling',
1925 b'showmin',
1935 b'showmin',
1926 default=dynamicdefault,
1936 default=dynamicdefault,
1927 )
1937 )
1928 coreconfigitem(
1938 coreconfigitem(
1929 b'profiling',
1939 b'profiling',
1930 b'showtime',
1940 b'showtime',
1931 default=True,
1941 default=True,
1932 )
1942 )
1933 coreconfigitem(
1943 coreconfigitem(
1934 b'profiling',
1944 b'profiling',
1935 b'sort',
1945 b'sort',
1936 default=b'inlinetime',
1946 default=b'inlinetime',
1937 )
1947 )
1938 coreconfigitem(
1948 coreconfigitem(
1939 b'profiling',
1949 b'profiling',
1940 b'statformat',
1950 b'statformat',
1941 default=b'hotpath',
1951 default=b'hotpath',
1942 )
1952 )
1943 coreconfigitem(
1953 coreconfigitem(
1944 b'profiling',
1954 b'profiling',
1945 b'time-track',
1955 b'time-track',
1946 default=dynamicdefault,
1956 default=dynamicdefault,
1947 )
1957 )
1948 coreconfigitem(
1958 coreconfigitem(
1949 b'profiling',
1959 b'profiling',
1950 b'type',
1960 b'type',
1951 default=b'stat',
1961 default=b'stat',
1952 )
1962 )
1953 coreconfigitem(
1963 coreconfigitem(
1954 b'progress',
1964 b'progress',
1955 b'assume-tty',
1965 b'assume-tty',
1956 default=False,
1966 default=False,
1957 )
1967 )
1958 coreconfigitem(
1968 coreconfigitem(
1959 b'progress',
1969 b'progress',
1960 b'changedelay',
1970 b'changedelay',
1961 default=1,
1971 default=1,
1962 )
1972 )
1963 coreconfigitem(
1973 coreconfigitem(
1964 b'progress',
1974 b'progress',
1965 b'clear-complete',
1975 b'clear-complete',
1966 default=True,
1976 default=True,
1967 )
1977 )
1968 coreconfigitem(
1978 coreconfigitem(
1969 b'progress',
1979 b'progress',
1970 b'debug',
1980 b'debug',
1971 default=False,
1981 default=False,
1972 )
1982 )
1973 coreconfigitem(
1983 coreconfigitem(
1974 b'progress',
1984 b'progress',
1975 b'delay',
1985 b'delay',
1976 default=3,
1986 default=3,
1977 )
1987 )
1978 coreconfigitem(
1988 coreconfigitem(
1979 b'progress',
1989 b'progress',
1980 b'disable',
1990 b'disable',
1981 default=False,
1991 default=False,
1982 )
1992 )
1983 coreconfigitem(
1993 coreconfigitem(
1984 b'progress',
1994 b'progress',
1985 b'estimateinterval',
1995 b'estimateinterval',
1986 default=60.0,
1996 default=60.0,
1987 )
1997 )
1988 coreconfigitem(
1998 coreconfigitem(
1989 b'progress',
1999 b'progress',
1990 b'format',
2000 b'format',
1991 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
2001 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1992 )
2002 )
1993 coreconfigitem(
2003 coreconfigitem(
1994 b'progress',
2004 b'progress',
1995 b'refresh',
2005 b'refresh',
1996 default=0.1,
2006 default=0.1,
1997 )
2007 )
1998 coreconfigitem(
2008 coreconfigitem(
1999 b'progress',
2009 b'progress',
2000 b'width',
2010 b'width',
2001 default=dynamicdefault,
2011 default=dynamicdefault,
2002 )
2012 )
2003 coreconfigitem(
2013 coreconfigitem(
2004 b'pull',
2014 b'pull',
2005 b'confirm',
2015 b'confirm',
2006 default=False,
2016 default=False,
2007 )
2017 )
2008 coreconfigitem(
2018 coreconfigitem(
2009 b'push',
2019 b'push',
2010 b'pushvars.server',
2020 b'pushvars.server',
2011 default=False,
2021 default=False,
2012 )
2022 )
2013 coreconfigitem(
2023 coreconfigitem(
2014 b'rewrite',
2024 b'rewrite',
2015 b'backup-bundle',
2025 b'backup-bundle',
2016 default=True,
2026 default=True,
2017 alias=[(b'ui', b'history-editing-backup')],
2027 alias=[(b'ui', b'history-editing-backup')],
2018 )
2028 )
2019 coreconfigitem(
2029 coreconfigitem(
2020 b'rewrite',
2030 b'rewrite',
2021 b'update-timestamp',
2031 b'update-timestamp',
2022 default=False,
2032 default=False,
2023 )
2033 )
2024 coreconfigitem(
2034 coreconfigitem(
2025 b'rewrite',
2035 b'rewrite',
2026 b'empty-successor',
2036 b'empty-successor',
2027 default=b'skip',
2037 default=b'skip',
2028 experimental=True,
2038 experimental=True,
2029 )
2039 )
2030 # experimental as long as format.use-dirstate-v2 is.
2040 # experimental as long as format.use-dirstate-v2 is.
2031 coreconfigitem(
2041 coreconfigitem(
2032 b'storage',
2042 b'storage',
2033 b'dirstate-v2.slow-path',
2043 b'dirstate-v2.slow-path',
2034 default=b"abort",
2044 default=b"abort",
2035 experimental=True,
2045 experimental=True,
2036 )
2046 )
2037 coreconfigitem(
2047 coreconfigitem(
2038 b'storage',
2048 b'storage',
2039 b'new-repo-backend',
2049 b'new-repo-backend',
2040 default=b'revlogv1',
2050 default=b'revlogv1',
2041 experimental=True,
2051 experimental=True,
2042 )
2052 )
2043 coreconfigitem(
2053 coreconfigitem(
2044 b'storage',
2054 b'storage',
2045 b'revlog.optimize-delta-parent-choice',
2055 b'revlog.optimize-delta-parent-choice',
2046 default=True,
2056 default=True,
2047 alias=[(b'format', b'aggressivemergedeltas')],
2057 alias=[(b'format', b'aggressivemergedeltas')],
2048 )
2058 )
2049 coreconfigitem(
2059 coreconfigitem(
2050 b'storage',
2060 b'storage',
2051 b'revlog.issue6528.fix-incoming',
2061 b'revlog.issue6528.fix-incoming',
2052 default=True,
2062 default=True,
2053 )
2063 )
2054 # experimental as long as rust is experimental (or a C version is implemented)
2064 # experimental as long as rust is experimental (or a C version is implemented)
2055 coreconfigitem(
2065 coreconfigitem(
2056 b'storage',
2066 b'storage',
2057 b'revlog.persistent-nodemap.mmap',
2067 b'revlog.persistent-nodemap.mmap',
2058 default=True,
2068 default=True,
2059 )
2069 )
2060 # experimental as long as format.use-persistent-nodemap is.
2070 # experimental as long as format.use-persistent-nodemap is.
2061 coreconfigitem(
2071 coreconfigitem(
2062 b'storage',
2072 b'storage',
2063 b'revlog.persistent-nodemap.slow-path',
2073 b'revlog.persistent-nodemap.slow-path',
2064 default=b"abort",
2074 default=b"abort",
2065 )
2075 )
2066
2076
2067 coreconfigitem(
2077 coreconfigitem(
2068 b'storage',
2078 b'storage',
2069 b'revlog.reuse-external-delta',
2079 b'revlog.reuse-external-delta',
2070 default=True,
2080 default=True,
2071 )
2081 )
2072 coreconfigitem(
2082 coreconfigitem(
2073 b'storage',
2083 b'storage',
2074 b'revlog.reuse-external-delta-parent',
2084 b'revlog.reuse-external-delta-parent',
2075 default=None,
2085 default=None,
2076 )
2086 )
2077 coreconfigitem(
2087 coreconfigitem(
2078 b'storage',
2088 b'storage',
2079 b'revlog.zlib.level',
2089 b'revlog.zlib.level',
2080 default=None,
2090 default=None,
2081 )
2091 )
2082 coreconfigitem(
2092 coreconfigitem(
2083 b'storage',
2093 b'storage',
2084 b'revlog.zstd.level',
2094 b'revlog.zstd.level',
2085 default=None,
2095 default=None,
2086 )
2096 )
2087 coreconfigitem(
2097 coreconfigitem(
2088 b'server',
2098 b'server',
2089 b'bookmarks-pushkey-compat',
2099 b'bookmarks-pushkey-compat',
2090 default=True,
2100 default=True,
2091 )
2101 )
2092 coreconfigitem(
2102 coreconfigitem(
2093 b'server',
2103 b'server',
2094 b'bundle1',
2104 b'bundle1',
2095 default=True,
2105 default=True,
2096 )
2106 )
2097 coreconfigitem(
2107 coreconfigitem(
2098 b'server',
2108 b'server',
2099 b'bundle1gd',
2109 b'bundle1gd',
2100 default=None,
2110 default=None,
2101 )
2111 )
2102 coreconfigitem(
2112 coreconfigitem(
2103 b'server',
2113 b'server',
2104 b'bundle1.pull',
2114 b'bundle1.pull',
2105 default=None,
2115 default=None,
2106 )
2116 )
2107 coreconfigitem(
2117 coreconfigitem(
2108 b'server',
2118 b'server',
2109 b'bundle1gd.pull',
2119 b'bundle1gd.pull',
2110 default=None,
2120 default=None,
2111 )
2121 )
2112 coreconfigitem(
2122 coreconfigitem(
2113 b'server',
2123 b'server',
2114 b'bundle1.push',
2124 b'bundle1.push',
2115 default=None,
2125 default=None,
2116 )
2126 )
2117 coreconfigitem(
2127 coreconfigitem(
2118 b'server',
2128 b'server',
2119 b'bundle1gd.push',
2129 b'bundle1gd.push',
2120 default=None,
2130 default=None,
2121 )
2131 )
2122 coreconfigitem(
2132 coreconfigitem(
2123 b'server',
2133 b'server',
2124 b'bundle2.stream',
2134 b'bundle2.stream',
2125 default=True,
2135 default=True,
2126 alias=[(b'experimental', b'bundle2.stream')],
2136 alias=[(b'experimental', b'bundle2.stream')],
2127 )
2137 )
2128 coreconfigitem(
2138 coreconfigitem(
2129 b'server',
2139 b'server',
2130 b'compressionengines',
2140 b'compressionengines',
2131 default=list,
2141 default=list,
2132 )
2142 )
2133 coreconfigitem(
2143 coreconfigitem(
2134 b'server',
2144 b'server',
2135 b'concurrent-push-mode',
2145 b'concurrent-push-mode',
2136 default=b'check-related',
2146 default=b'check-related',
2137 )
2147 )
2138 coreconfigitem(
2148 coreconfigitem(
2139 b'server',
2149 b'server',
2140 b'disablefullbundle',
2150 b'disablefullbundle',
2141 default=False,
2151 default=False,
2142 )
2152 )
2143 coreconfigitem(
2153 coreconfigitem(
2144 b'server',
2154 b'server',
2145 b'maxhttpheaderlen',
2155 b'maxhttpheaderlen',
2146 default=1024,
2156 default=1024,
2147 )
2157 )
2148 coreconfigitem(
2158 coreconfigitem(
2149 b'server',
2159 b'server',
2150 b'pullbundle',
2160 b'pullbundle',
2151 default=False,
2161 default=False,
2152 )
2162 )
2153 coreconfigitem(
2163 coreconfigitem(
2154 b'server',
2164 b'server',
2155 b'preferuncompressed',
2165 b'preferuncompressed',
2156 default=False,
2166 default=False,
2157 )
2167 )
2158 coreconfigitem(
2168 coreconfigitem(
2159 b'server',
2169 b'server',
2160 b'streamunbundle',
2170 b'streamunbundle',
2161 default=False,
2171 default=False,
2162 )
2172 )
2163 coreconfigitem(
2173 coreconfigitem(
2164 b'server',
2174 b'server',
2165 b'uncompressed',
2175 b'uncompressed',
2166 default=True,
2176 default=True,
2167 )
2177 )
2168 coreconfigitem(
2178 coreconfigitem(
2169 b'server',
2179 b'server',
2170 b'uncompressedallowsecret',
2180 b'uncompressedallowsecret',
2171 default=False,
2181 default=False,
2172 )
2182 )
2173 coreconfigitem(
2183 coreconfigitem(
2174 b'server',
2184 b'server',
2175 b'view',
2185 b'view',
2176 default=b'served',
2186 default=b'served',
2177 )
2187 )
2178 coreconfigitem(
2188 coreconfigitem(
2179 b'server',
2189 b'server',
2180 b'validate',
2190 b'validate',
2181 default=False,
2191 default=False,
2182 )
2192 )
2183 coreconfigitem(
2193 coreconfigitem(
2184 b'server',
2194 b'server',
2185 b'zliblevel',
2195 b'zliblevel',
2186 default=-1,
2196 default=-1,
2187 )
2197 )
2188 coreconfigitem(
2198 coreconfigitem(
2189 b'server',
2199 b'server',
2190 b'zstdlevel',
2200 b'zstdlevel',
2191 default=3,
2201 default=3,
2192 )
2202 )
2193 coreconfigitem(
2203 coreconfigitem(
2194 b'share',
2204 b'share',
2195 b'pool',
2205 b'pool',
2196 default=None,
2206 default=None,
2197 )
2207 )
2198 coreconfigitem(
2208 coreconfigitem(
2199 b'share',
2209 b'share',
2200 b'poolnaming',
2210 b'poolnaming',
2201 default=b'identity',
2211 default=b'identity',
2202 )
2212 )
2203 coreconfigitem(
2213 coreconfigitem(
2204 b'share',
2214 b'share',
2205 b'safe-mismatch.source-not-safe',
2215 b'safe-mismatch.source-not-safe',
2206 default=b'abort',
2216 default=b'abort',
2207 )
2217 )
2208 coreconfigitem(
2218 coreconfigitem(
2209 b'share',
2219 b'share',
2210 b'safe-mismatch.source-safe',
2220 b'safe-mismatch.source-safe',
2211 default=b'abort',
2221 default=b'abort',
2212 )
2222 )
2213 coreconfigitem(
2223 coreconfigitem(
2214 b'share',
2224 b'share',
2215 b'safe-mismatch.source-not-safe.warn',
2225 b'safe-mismatch.source-not-safe.warn',
2216 default=True,
2226 default=True,
2217 )
2227 )
2218 coreconfigitem(
2228 coreconfigitem(
2219 b'share',
2229 b'share',
2220 b'safe-mismatch.source-safe.warn',
2230 b'safe-mismatch.source-safe.warn',
2221 default=True,
2231 default=True,
2222 )
2232 )
2223 coreconfigitem(
2233 coreconfigitem(
2224 b'share',
2234 b'share',
2225 b'safe-mismatch.source-not-safe:verbose-upgrade',
2235 b'safe-mismatch.source-not-safe:verbose-upgrade',
2226 default=True,
2236 default=True,
2227 )
2237 )
2228 coreconfigitem(
2238 coreconfigitem(
2229 b'share',
2239 b'share',
2230 b'safe-mismatch.source-safe:verbose-upgrade',
2240 b'safe-mismatch.source-safe:verbose-upgrade',
2231 default=True,
2241 default=True,
2232 )
2242 )
2233 coreconfigitem(
2243 coreconfigitem(
2234 b'shelve',
2244 b'shelve',
2235 b'maxbackups',
2245 b'maxbackups',
2236 default=10,
2246 default=10,
2237 )
2247 )
2238 coreconfigitem(
2248 coreconfigitem(
2239 b'smtp',
2249 b'smtp',
2240 b'host',
2250 b'host',
2241 default=None,
2251 default=None,
2242 )
2252 )
2243 coreconfigitem(
2253 coreconfigitem(
2244 b'smtp',
2254 b'smtp',
2245 b'local_hostname',
2255 b'local_hostname',
2246 default=None,
2256 default=None,
2247 )
2257 )
2248 coreconfigitem(
2258 coreconfigitem(
2249 b'smtp',
2259 b'smtp',
2250 b'password',
2260 b'password',
2251 default=None,
2261 default=None,
2252 )
2262 )
2253 coreconfigitem(
2263 coreconfigitem(
2254 b'smtp',
2264 b'smtp',
2255 b'port',
2265 b'port',
2256 default=dynamicdefault,
2266 default=dynamicdefault,
2257 )
2267 )
2258 coreconfigitem(
2268 coreconfigitem(
2259 b'smtp',
2269 b'smtp',
2260 b'tls',
2270 b'tls',
2261 default=b'none',
2271 default=b'none',
2262 )
2272 )
2263 coreconfigitem(
2273 coreconfigitem(
2264 b'smtp',
2274 b'smtp',
2265 b'username',
2275 b'username',
2266 default=None,
2276 default=None,
2267 )
2277 )
2268 coreconfigitem(
2278 coreconfigitem(
2269 b'sparse',
2279 b'sparse',
2270 b'missingwarning',
2280 b'missingwarning',
2271 default=True,
2281 default=True,
2272 experimental=True,
2282 experimental=True,
2273 )
2283 )
2274 coreconfigitem(
2284 coreconfigitem(
2275 b'subrepos',
2285 b'subrepos',
2276 b'allowed',
2286 b'allowed',
2277 default=dynamicdefault, # to make backporting simpler
2287 default=dynamicdefault, # to make backporting simpler
2278 )
2288 )
2279 coreconfigitem(
2289 coreconfigitem(
2280 b'subrepos',
2290 b'subrepos',
2281 b'hg:allowed',
2291 b'hg:allowed',
2282 default=dynamicdefault,
2292 default=dynamicdefault,
2283 )
2293 )
2284 coreconfigitem(
2294 coreconfigitem(
2285 b'subrepos',
2295 b'subrepos',
2286 b'git:allowed',
2296 b'git:allowed',
2287 default=dynamicdefault,
2297 default=dynamicdefault,
2288 )
2298 )
2289 coreconfigitem(
2299 coreconfigitem(
2290 b'subrepos',
2300 b'subrepos',
2291 b'svn:allowed',
2301 b'svn:allowed',
2292 default=dynamicdefault,
2302 default=dynamicdefault,
2293 )
2303 )
2294 coreconfigitem(
2304 coreconfigitem(
2295 b'templates',
2305 b'templates',
2296 b'.*',
2306 b'.*',
2297 default=None,
2307 default=None,
2298 generic=True,
2308 generic=True,
2299 )
2309 )
2300 coreconfigitem(
2310 coreconfigitem(
2301 b'templateconfig',
2311 b'templateconfig',
2302 b'.*',
2312 b'.*',
2303 default=dynamicdefault,
2313 default=dynamicdefault,
2304 generic=True,
2314 generic=True,
2305 )
2315 )
2306 coreconfigitem(
2316 coreconfigitem(
2307 b'trusted',
2317 b'trusted',
2308 b'groups',
2318 b'groups',
2309 default=list,
2319 default=list,
2310 )
2320 )
2311 coreconfigitem(
2321 coreconfigitem(
2312 b'trusted',
2322 b'trusted',
2313 b'users',
2323 b'users',
2314 default=list,
2324 default=list,
2315 )
2325 )
2316 coreconfigitem(
2326 coreconfigitem(
2317 b'ui',
2327 b'ui',
2318 b'_usedassubrepo',
2328 b'_usedassubrepo',
2319 default=False,
2329 default=False,
2320 )
2330 )
2321 coreconfigitem(
2331 coreconfigitem(
2322 b'ui',
2332 b'ui',
2323 b'allowemptycommit',
2333 b'allowemptycommit',
2324 default=False,
2334 default=False,
2325 )
2335 )
2326 coreconfigitem(
2336 coreconfigitem(
2327 b'ui',
2337 b'ui',
2328 b'archivemeta',
2338 b'archivemeta',
2329 default=True,
2339 default=True,
2330 )
2340 )
2331 coreconfigitem(
2341 coreconfigitem(
2332 b'ui',
2342 b'ui',
2333 b'askusername',
2343 b'askusername',
2334 default=False,
2344 default=False,
2335 )
2345 )
2336 coreconfigitem(
2346 coreconfigitem(
2337 b'ui',
2347 b'ui',
2338 b'available-memory',
2348 b'available-memory',
2339 default=None,
2349 default=None,
2340 )
2350 )
2341
2351
2342 coreconfigitem(
2352 coreconfigitem(
2343 b'ui',
2353 b'ui',
2344 b'clonebundlefallback',
2354 b'clonebundlefallback',
2345 default=False,
2355 default=False,
2346 )
2356 )
2347 coreconfigitem(
2357 coreconfigitem(
2348 b'ui',
2358 b'ui',
2349 b'clonebundleprefers',
2359 b'clonebundleprefers',
2350 default=list,
2360 default=list,
2351 )
2361 )
2352 coreconfigitem(
2362 coreconfigitem(
2353 b'ui',
2363 b'ui',
2354 b'clonebundles',
2364 b'clonebundles',
2355 default=True,
2365 default=True,
2356 )
2366 )
2357 coreconfigitem(
2367 coreconfigitem(
2358 b'ui',
2368 b'ui',
2359 b'color',
2369 b'color',
2360 default=b'auto',
2370 default=b'auto',
2361 )
2371 )
2362 coreconfigitem(
2372 coreconfigitem(
2363 b'ui',
2373 b'ui',
2364 b'commitsubrepos',
2374 b'commitsubrepos',
2365 default=False,
2375 default=False,
2366 )
2376 )
2367 coreconfigitem(
2377 coreconfigitem(
2368 b'ui',
2378 b'ui',
2369 b'debug',
2379 b'debug',
2370 default=False,
2380 default=False,
2371 )
2381 )
2372 coreconfigitem(
2382 coreconfigitem(
2373 b'ui',
2383 b'ui',
2374 b'debugger',
2384 b'debugger',
2375 default=None,
2385 default=None,
2376 )
2386 )
2377 coreconfigitem(
2387 coreconfigitem(
2378 b'ui',
2388 b'ui',
2379 b'editor',
2389 b'editor',
2380 default=dynamicdefault,
2390 default=dynamicdefault,
2381 )
2391 )
2382 coreconfigitem(
2392 coreconfigitem(
2383 b'ui',
2393 b'ui',
2384 b'detailed-exit-code',
2394 b'detailed-exit-code',
2385 default=False,
2395 default=False,
2386 experimental=True,
2396 experimental=True,
2387 )
2397 )
2388 coreconfigitem(
2398 coreconfigitem(
2389 b'ui',
2399 b'ui',
2390 b'fallbackencoding',
2400 b'fallbackencoding',
2391 default=None,
2401 default=None,
2392 )
2402 )
2393 coreconfigitem(
2403 coreconfigitem(
2394 b'ui',
2404 b'ui',
2395 b'forcecwd',
2405 b'forcecwd',
2396 default=None,
2406 default=None,
2397 )
2407 )
2398 coreconfigitem(
2408 coreconfigitem(
2399 b'ui',
2409 b'ui',
2400 b'forcemerge',
2410 b'forcemerge',
2401 default=None,
2411 default=None,
2402 )
2412 )
2403 coreconfigitem(
2413 coreconfigitem(
2404 b'ui',
2414 b'ui',
2405 b'formatdebug',
2415 b'formatdebug',
2406 default=False,
2416 default=False,
2407 )
2417 )
2408 coreconfigitem(
2418 coreconfigitem(
2409 b'ui',
2419 b'ui',
2410 b'formatjson',
2420 b'formatjson',
2411 default=False,
2421 default=False,
2412 )
2422 )
2413 coreconfigitem(
2423 coreconfigitem(
2414 b'ui',
2424 b'ui',
2415 b'formatted',
2425 b'formatted',
2416 default=None,
2426 default=None,
2417 )
2427 )
2418 coreconfigitem(
2428 coreconfigitem(
2419 b'ui',
2429 b'ui',
2420 b'interactive',
2430 b'interactive',
2421 default=None,
2431 default=None,
2422 )
2432 )
2423 coreconfigitem(
2433 coreconfigitem(
2424 b'ui',
2434 b'ui',
2425 b'interface',
2435 b'interface',
2426 default=None,
2436 default=None,
2427 )
2437 )
2428 coreconfigitem(
2438 coreconfigitem(
2429 b'ui',
2439 b'ui',
2430 b'interface.chunkselector',
2440 b'interface.chunkselector',
2431 default=None,
2441 default=None,
2432 )
2442 )
2433 coreconfigitem(
2443 coreconfigitem(
2434 b'ui',
2444 b'ui',
2435 b'large-file-limit',
2445 b'large-file-limit',
2436 default=10 * (2 ** 20),
2446 default=10 * (2 ** 20),
2437 )
2447 )
2438 coreconfigitem(
2448 coreconfigitem(
2439 b'ui',
2449 b'ui',
2440 b'logblockedtimes',
2450 b'logblockedtimes',
2441 default=False,
2451 default=False,
2442 )
2452 )
2443 coreconfigitem(
2453 coreconfigitem(
2444 b'ui',
2454 b'ui',
2445 b'merge',
2455 b'merge',
2446 default=None,
2456 default=None,
2447 )
2457 )
2448 coreconfigitem(
2458 coreconfigitem(
2449 b'ui',
2459 b'ui',
2450 b'mergemarkers',
2460 b'mergemarkers',
2451 default=b'basic',
2461 default=b'basic',
2452 )
2462 )
2453 coreconfigitem(
2463 coreconfigitem(
2454 b'ui',
2464 b'ui',
2455 b'message-output',
2465 b'message-output',
2456 default=b'stdio',
2466 default=b'stdio',
2457 )
2467 )
2458 coreconfigitem(
2468 coreconfigitem(
2459 b'ui',
2469 b'ui',
2460 b'nontty',
2470 b'nontty',
2461 default=False,
2471 default=False,
2462 )
2472 )
2463 coreconfigitem(
2473 coreconfigitem(
2464 b'ui',
2474 b'ui',
2465 b'origbackuppath',
2475 b'origbackuppath',
2466 default=None,
2476 default=None,
2467 )
2477 )
2468 coreconfigitem(
2478 coreconfigitem(
2469 b'ui',
2479 b'ui',
2470 b'paginate',
2480 b'paginate',
2471 default=True,
2481 default=True,
2472 )
2482 )
2473 coreconfigitem(
2483 coreconfigitem(
2474 b'ui',
2484 b'ui',
2475 b'patch',
2485 b'patch',
2476 default=None,
2486 default=None,
2477 )
2487 )
2478 coreconfigitem(
2488 coreconfigitem(
2479 b'ui',
2489 b'ui',
2480 b'portablefilenames',
2490 b'portablefilenames',
2481 default=b'warn',
2491 default=b'warn',
2482 )
2492 )
2483 coreconfigitem(
2493 coreconfigitem(
2484 b'ui',
2494 b'ui',
2485 b'promptecho',
2495 b'promptecho',
2486 default=False,
2496 default=False,
2487 )
2497 )
2488 coreconfigitem(
2498 coreconfigitem(
2489 b'ui',
2499 b'ui',
2490 b'quiet',
2500 b'quiet',
2491 default=False,
2501 default=False,
2492 )
2502 )
2493 coreconfigitem(
2503 coreconfigitem(
2494 b'ui',
2504 b'ui',
2495 b'quietbookmarkmove',
2505 b'quietbookmarkmove',
2496 default=False,
2506 default=False,
2497 )
2507 )
2498 coreconfigitem(
2508 coreconfigitem(
2499 b'ui',
2509 b'ui',
2500 b'relative-paths',
2510 b'relative-paths',
2501 default=b'legacy',
2511 default=b'legacy',
2502 )
2512 )
2503 coreconfigitem(
2513 coreconfigitem(
2504 b'ui',
2514 b'ui',
2505 b'remotecmd',
2515 b'remotecmd',
2506 default=b'hg',
2516 default=b'hg',
2507 )
2517 )
2508 coreconfigitem(
2518 coreconfigitem(
2509 b'ui',
2519 b'ui',
2510 b'report_untrusted',
2520 b'report_untrusted',
2511 default=True,
2521 default=True,
2512 )
2522 )
2513 coreconfigitem(
2523 coreconfigitem(
2514 b'ui',
2524 b'ui',
2515 b'rollback',
2525 b'rollback',
2516 default=True,
2526 default=True,
2517 )
2527 )
2518 coreconfigitem(
2528 coreconfigitem(
2519 b'ui',
2529 b'ui',
2520 b'signal-safe-lock',
2530 b'signal-safe-lock',
2521 default=True,
2531 default=True,
2522 )
2532 )
2523 coreconfigitem(
2533 coreconfigitem(
2524 b'ui',
2534 b'ui',
2525 b'slash',
2535 b'slash',
2526 default=False,
2536 default=False,
2527 )
2537 )
2528 coreconfigitem(
2538 coreconfigitem(
2529 b'ui',
2539 b'ui',
2530 b'ssh',
2540 b'ssh',
2531 default=b'ssh',
2541 default=b'ssh',
2532 )
2542 )
2533 coreconfigitem(
2543 coreconfigitem(
2534 b'ui',
2544 b'ui',
2535 b'ssherrorhint',
2545 b'ssherrorhint',
2536 default=None,
2546 default=None,
2537 )
2547 )
2538 coreconfigitem(
2548 coreconfigitem(
2539 b'ui',
2549 b'ui',
2540 b'statuscopies',
2550 b'statuscopies',
2541 default=False,
2551 default=False,
2542 )
2552 )
2543 coreconfigitem(
2553 coreconfigitem(
2544 b'ui',
2554 b'ui',
2545 b'strict',
2555 b'strict',
2546 default=False,
2556 default=False,
2547 )
2557 )
2548 coreconfigitem(
2558 coreconfigitem(
2549 b'ui',
2559 b'ui',
2550 b'style',
2560 b'style',
2551 default=b'',
2561 default=b'',
2552 )
2562 )
2553 coreconfigitem(
2563 coreconfigitem(
2554 b'ui',
2564 b'ui',
2555 b'supportcontact',
2565 b'supportcontact',
2556 default=None,
2566 default=None,
2557 )
2567 )
2558 coreconfigitem(
2568 coreconfigitem(
2559 b'ui',
2569 b'ui',
2560 b'textwidth',
2570 b'textwidth',
2561 default=78,
2571 default=78,
2562 )
2572 )
2563 coreconfigitem(
2573 coreconfigitem(
2564 b'ui',
2574 b'ui',
2565 b'timeout',
2575 b'timeout',
2566 default=b'600',
2576 default=b'600',
2567 )
2577 )
2568 coreconfigitem(
2578 coreconfigitem(
2569 b'ui',
2579 b'ui',
2570 b'timeout.warn',
2580 b'timeout.warn',
2571 default=0,
2581 default=0,
2572 )
2582 )
2573 coreconfigitem(
2583 coreconfigitem(
2574 b'ui',
2584 b'ui',
2575 b'timestamp-output',
2585 b'timestamp-output',
2576 default=False,
2586 default=False,
2577 )
2587 )
2578 coreconfigitem(
2588 coreconfigitem(
2579 b'ui',
2589 b'ui',
2580 b'traceback',
2590 b'traceback',
2581 default=False,
2591 default=False,
2582 )
2592 )
2583 coreconfigitem(
2593 coreconfigitem(
2584 b'ui',
2594 b'ui',
2585 b'tweakdefaults',
2595 b'tweakdefaults',
2586 default=False,
2596 default=False,
2587 )
2597 )
2588 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2598 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2589 coreconfigitem(
2599 coreconfigitem(
2590 b'ui',
2600 b'ui',
2591 b'verbose',
2601 b'verbose',
2592 default=False,
2602 default=False,
2593 )
2603 )
2594 coreconfigitem(
2604 coreconfigitem(
2595 b'verify',
2605 b'verify',
2596 b'skipflags',
2606 b'skipflags',
2597 default=0,
2607 default=0,
2598 )
2608 )
2599 coreconfigitem(
2609 coreconfigitem(
2600 b'web',
2610 b'web',
2601 b'allowbz2',
2611 b'allowbz2',
2602 default=False,
2612 default=False,
2603 )
2613 )
2604 coreconfigitem(
2614 coreconfigitem(
2605 b'web',
2615 b'web',
2606 b'allowgz',
2616 b'allowgz',
2607 default=False,
2617 default=False,
2608 )
2618 )
2609 coreconfigitem(
2619 coreconfigitem(
2610 b'web',
2620 b'web',
2611 b'allow-pull',
2621 b'allow-pull',
2612 alias=[(b'web', b'allowpull')],
2622 alias=[(b'web', b'allowpull')],
2613 default=True,
2623 default=True,
2614 )
2624 )
2615 coreconfigitem(
2625 coreconfigitem(
2616 b'web',
2626 b'web',
2617 b'allow-push',
2627 b'allow-push',
2618 alias=[(b'web', b'allow_push')],
2628 alias=[(b'web', b'allow_push')],
2619 default=list,
2629 default=list,
2620 )
2630 )
2621 coreconfigitem(
2631 coreconfigitem(
2622 b'web',
2632 b'web',
2623 b'allowzip',
2633 b'allowzip',
2624 default=False,
2634 default=False,
2625 )
2635 )
2626 coreconfigitem(
2636 coreconfigitem(
2627 b'web',
2637 b'web',
2628 b'archivesubrepos',
2638 b'archivesubrepos',
2629 default=False,
2639 default=False,
2630 )
2640 )
2631 coreconfigitem(
2641 coreconfigitem(
2632 b'web',
2642 b'web',
2633 b'cache',
2643 b'cache',
2634 default=True,
2644 default=True,
2635 )
2645 )
2636 coreconfigitem(
2646 coreconfigitem(
2637 b'web',
2647 b'web',
2638 b'comparisoncontext',
2648 b'comparisoncontext',
2639 default=5,
2649 default=5,
2640 )
2650 )
2641 coreconfigitem(
2651 coreconfigitem(
2642 b'web',
2652 b'web',
2643 b'contact',
2653 b'contact',
2644 default=None,
2654 default=None,
2645 )
2655 )
2646 coreconfigitem(
2656 coreconfigitem(
2647 b'web',
2657 b'web',
2648 b'deny_push',
2658 b'deny_push',
2649 default=list,
2659 default=list,
2650 )
2660 )
2651 coreconfigitem(
2661 coreconfigitem(
2652 b'web',
2662 b'web',
2653 b'guessmime',
2663 b'guessmime',
2654 default=False,
2664 default=False,
2655 )
2665 )
2656 coreconfigitem(
2666 coreconfigitem(
2657 b'web',
2667 b'web',
2658 b'hidden',
2668 b'hidden',
2659 default=False,
2669 default=False,
2660 )
2670 )
2661 coreconfigitem(
2671 coreconfigitem(
2662 b'web',
2672 b'web',
2663 b'labels',
2673 b'labels',
2664 default=list,
2674 default=list,
2665 )
2675 )
2666 coreconfigitem(
2676 coreconfigitem(
2667 b'web',
2677 b'web',
2668 b'logoimg',
2678 b'logoimg',
2669 default=b'hglogo.png',
2679 default=b'hglogo.png',
2670 )
2680 )
2671 coreconfigitem(
2681 coreconfigitem(
2672 b'web',
2682 b'web',
2673 b'logourl',
2683 b'logourl',
2674 default=b'https://mercurial-scm.org/',
2684 default=b'https://mercurial-scm.org/',
2675 )
2685 )
2676 coreconfigitem(
2686 coreconfigitem(
2677 b'web',
2687 b'web',
2678 b'accesslog',
2688 b'accesslog',
2679 default=b'-',
2689 default=b'-',
2680 )
2690 )
2681 coreconfigitem(
2691 coreconfigitem(
2682 b'web',
2692 b'web',
2683 b'address',
2693 b'address',
2684 default=b'',
2694 default=b'',
2685 )
2695 )
2686 coreconfigitem(
2696 coreconfigitem(
2687 b'web',
2697 b'web',
2688 b'allow-archive',
2698 b'allow-archive',
2689 alias=[(b'web', b'allow_archive')],
2699 alias=[(b'web', b'allow_archive')],
2690 default=list,
2700 default=list,
2691 )
2701 )
2692 coreconfigitem(
2702 coreconfigitem(
2693 b'web',
2703 b'web',
2694 b'allow_read',
2704 b'allow_read',
2695 default=list,
2705 default=list,
2696 )
2706 )
2697 coreconfigitem(
2707 coreconfigitem(
2698 b'web',
2708 b'web',
2699 b'baseurl',
2709 b'baseurl',
2700 default=None,
2710 default=None,
2701 )
2711 )
2702 coreconfigitem(
2712 coreconfigitem(
2703 b'web',
2713 b'web',
2704 b'cacerts',
2714 b'cacerts',
2705 default=None,
2715 default=None,
2706 )
2716 )
2707 coreconfigitem(
2717 coreconfigitem(
2708 b'web',
2718 b'web',
2709 b'certificate',
2719 b'certificate',
2710 default=None,
2720 default=None,
2711 )
2721 )
2712 coreconfigitem(
2722 coreconfigitem(
2713 b'web',
2723 b'web',
2714 b'collapse',
2724 b'collapse',
2715 default=False,
2725 default=False,
2716 )
2726 )
2717 coreconfigitem(
2727 coreconfigitem(
2718 b'web',
2728 b'web',
2719 b'csp',
2729 b'csp',
2720 default=None,
2730 default=None,
2721 )
2731 )
2722 coreconfigitem(
2732 coreconfigitem(
2723 b'web',
2733 b'web',
2724 b'deny_read',
2734 b'deny_read',
2725 default=list,
2735 default=list,
2726 )
2736 )
2727 coreconfigitem(
2737 coreconfigitem(
2728 b'web',
2738 b'web',
2729 b'descend',
2739 b'descend',
2730 default=True,
2740 default=True,
2731 )
2741 )
2732 coreconfigitem(
2742 coreconfigitem(
2733 b'web',
2743 b'web',
2734 b'description',
2744 b'description',
2735 default=b"",
2745 default=b"",
2736 )
2746 )
2737 coreconfigitem(
2747 coreconfigitem(
2738 b'web',
2748 b'web',
2739 b'encoding',
2749 b'encoding',
2740 default=lambda: encoding.encoding,
2750 default=lambda: encoding.encoding,
2741 )
2751 )
2742 coreconfigitem(
2752 coreconfigitem(
2743 b'web',
2753 b'web',
2744 b'errorlog',
2754 b'errorlog',
2745 default=b'-',
2755 default=b'-',
2746 )
2756 )
2747 coreconfigitem(
2757 coreconfigitem(
2748 b'web',
2758 b'web',
2749 b'ipv6',
2759 b'ipv6',
2750 default=False,
2760 default=False,
2751 )
2761 )
2752 coreconfigitem(
2762 coreconfigitem(
2753 b'web',
2763 b'web',
2754 b'maxchanges',
2764 b'maxchanges',
2755 default=10,
2765 default=10,
2756 )
2766 )
2757 coreconfigitem(
2767 coreconfigitem(
2758 b'web',
2768 b'web',
2759 b'maxfiles',
2769 b'maxfiles',
2760 default=10,
2770 default=10,
2761 )
2771 )
2762 coreconfigitem(
2772 coreconfigitem(
2763 b'web',
2773 b'web',
2764 b'maxshortchanges',
2774 b'maxshortchanges',
2765 default=60,
2775 default=60,
2766 )
2776 )
2767 coreconfigitem(
2777 coreconfigitem(
2768 b'web',
2778 b'web',
2769 b'motd',
2779 b'motd',
2770 default=b'',
2780 default=b'',
2771 )
2781 )
2772 coreconfigitem(
2782 coreconfigitem(
2773 b'web',
2783 b'web',
2774 b'name',
2784 b'name',
2775 default=dynamicdefault,
2785 default=dynamicdefault,
2776 )
2786 )
2777 coreconfigitem(
2787 coreconfigitem(
2778 b'web',
2788 b'web',
2779 b'port',
2789 b'port',
2780 default=8000,
2790 default=8000,
2781 )
2791 )
2782 coreconfigitem(
2792 coreconfigitem(
2783 b'web',
2793 b'web',
2784 b'prefix',
2794 b'prefix',
2785 default=b'',
2795 default=b'',
2786 )
2796 )
2787 coreconfigitem(
2797 coreconfigitem(
2788 b'web',
2798 b'web',
2789 b'push_ssl',
2799 b'push_ssl',
2790 default=True,
2800 default=True,
2791 )
2801 )
2792 coreconfigitem(
2802 coreconfigitem(
2793 b'web',
2803 b'web',
2794 b'refreshinterval',
2804 b'refreshinterval',
2795 default=20,
2805 default=20,
2796 )
2806 )
2797 coreconfigitem(
2807 coreconfigitem(
2798 b'web',
2808 b'web',
2799 b'server-header',
2809 b'server-header',
2800 default=None,
2810 default=None,
2801 )
2811 )
2802 coreconfigitem(
2812 coreconfigitem(
2803 b'web',
2813 b'web',
2804 b'static',
2814 b'static',
2805 default=None,
2815 default=None,
2806 )
2816 )
2807 coreconfigitem(
2817 coreconfigitem(
2808 b'web',
2818 b'web',
2809 b'staticurl',
2819 b'staticurl',
2810 default=None,
2820 default=None,
2811 )
2821 )
2812 coreconfigitem(
2822 coreconfigitem(
2813 b'web',
2823 b'web',
2814 b'stripes',
2824 b'stripes',
2815 default=1,
2825 default=1,
2816 )
2826 )
2817 coreconfigitem(
2827 coreconfigitem(
2818 b'web',
2828 b'web',
2819 b'style',
2829 b'style',
2820 default=b'paper',
2830 default=b'paper',
2821 )
2831 )
2822 coreconfigitem(
2832 coreconfigitem(
2823 b'web',
2833 b'web',
2824 b'templates',
2834 b'templates',
2825 default=None,
2835 default=None,
2826 )
2836 )
2827 coreconfigitem(
2837 coreconfigitem(
2828 b'web',
2838 b'web',
2829 b'view',
2839 b'view',
2830 default=b'served',
2840 default=b'served',
2831 experimental=True,
2841 experimental=True,
2832 )
2842 )
2833 coreconfigitem(
2843 coreconfigitem(
2834 b'worker',
2844 b'worker',
2835 b'backgroundclose',
2845 b'backgroundclose',
2836 default=dynamicdefault,
2846 default=dynamicdefault,
2837 )
2847 )
2838 # Windows defaults to a limit of 512 open files. A buffer of 128
2848 # Windows defaults to a limit of 512 open files. A buffer of 128
2839 # should give us enough headway.
2849 # should give us enough headway.
2840 coreconfigitem(
2850 coreconfigitem(
2841 b'worker',
2851 b'worker',
2842 b'backgroundclosemaxqueue',
2852 b'backgroundclosemaxqueue',
2843 default=384,
2853 default=384,
2844 )
2854 )
2845 coreconfigitem(
2855 coreconfigitem(
2846 b'worker',
2856 b'worker',
2847 b'backgroundcloseminfilecount',
2857 b'backgroundcloseminfilecount',
2848 default=2048,
2858 default=2048,
2849 )
2859 )
2850 coreconfigitem(
2860 coreconfigitem(
2851 b'worker',
2861 b'worker',
2852 b'backgroundclosethreadcount',
2862 b'backgroundclosethreadcount',
2853 default=4,
2863 default=4,
2854 )
2864 )
2855 coreconfigitem(
2865 coreconfigitem(
2856 b'worker',
2866 b'worker',
2857 b'enabled',
2867 b'enabled',
2858 default=True,
2868 default=True,
2859 )
2869 )
2860 coreconfigitem(
2870 coreconfigitem(
2861 b'worker',
2871 b'worker',
2862 b'numcpus',
2872 b'numcpus',
2863 default=None,
2873 default=None,
2864 )
2874 )
2865
2875
2866 # Rebase related configuration moved to core because other extension are doing
2876 # Rebase related configuration moved to core because other extension are doing
2867 # strange things. For example, shelve import the extensions to reuse some bit
2877 # strange things. For example, shelve import the extensions to reuse some bit
2868 # without formally loading it.
2878 # without formally loading it.
2869 coreconfigitem(
2879 coreconfigitem(
2870 b'commands',
2880 b'commands',
2871 b'rebase.requiredest',
2881 b'rebase.requiredest',
2872 default=False,
2882 default=False,
2873 )
2883 )
2874 coreconfigitem(
2884 coreconfigitem(
2875 b'experimental',
2885 b'experimental',
2876 b'rebaseskipobsolete',
2886 b'rebaseskipobsolete',
2877 default=True,
2887 default=True,
2878 )
2888 )
2879 coreconfigitem(
2889 coreconfigitem(
2880 b'rebase',
2890 b'rebase',
2881 b'singletransaction',
2891 b'singletransaction',
2882 default=False,
2892 default=False,
2883 )
2893 )
2884 coreconfigitem(
2894 coreconfigitem(
2885 b'rebase',
2895 b'rebase',
2886 b'experimental.inmemory',
2896 b'experimental.inmemory',
2887 default=False,
2897 default=False,
2888 )
2898 )
2889
2899
2890 # This setting controls creation of a rebase_source extra field
2900 # This setting controls creation of a rebase_source extra field
2891 # during rebase. When False, no such field is created. This is
2901 # during rebase. When False, no such field is created. This is
2892 # useful eg for incrementally converting changesets and then
2902 # useful eg for incrementally converting changesets and then
2893 # rebasing them onto an existing repo.
2903 # rebasing them onto an existing repo.
2894 # WARNING: this is an advanced setting reserved for people who know
2904 # WARNING: this is an advanced setting reserved for people who know
2895 # exactly what they are doing. Misuse of this setting can easily
2905 # exactly what they are doing. Misuse of this setting can easily
2896 # result in obsmarker cycles and a vivid headache.
2906 # result in obsmarker cycles and a vivid headache.
2897 coreconfigitem(
2907 coreconfigitem(
2898 b'rebase',
2908 b'rebase',
2899 b'store-source',
2909 b'store-source',
2900 default=True,
2910 default=True,
2901 experimental=True,
2911 experimental=True,
2902 )
2912 )
@@ -1,704 +1,708 b''
1 # dirstatemap.py
1 # dirstatemap.py
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6
6
7 from .i18n import _
7 from .i18n import _
8
8
9 from . import (
9 from . import (
10 error,
10 error,
11 pathutil,
11 pathutil,
12 policy,
12 policy,
13 testing,
13 txnutil,
14 txnutil,
14 util,
15 util,
15 )
16 )
16
17
17 from .dirstateutils import (
18 from .dirstateutils import (
18 docket as docketmod,
19 docket as docketmod,
19 v2,
20 v2,
20 )
21 )
21
22
22 parsers = policy.importmod('parsers')
23 parsers = policy.importmod('parsers')
23 rustmod = policy.importrust('dirstate')
24 rustmod = policy.importrust('dirstate')
24
25
25 propertycache = util.propertycache
26 propertycache = util.propertycache
26
27
27 if rustmod is None:
28 if rustmod is None:
28 DirstateItem = parsers.DirstateItem
29 DirstateItem = parsers.DirstateItem
29 else:
30 else:
30 DirstateItem = rustmod.DirstateItem
31 DirstateItem = rustmod.DirstateItem
31
32
32 rangemask = 0x7FFFFFFF
33 rangemask = 0x7FFFFFFF
33
34
34 WRITE_MODE_AUTO = 0
35 WRITE_MODE_AUTO = 0
35 WRITE_MODE_FORCE_NEW = 1
36 WRITE_MODE_FORCE_NEW = 1
36 WRITE_MODE_FORCE_APPEND = 2
37 WRITE_MODE_FORCE_APPEND = 2
37
38
38
39
39 class _dirstatemapcommon:
40 class _dirstatemapcommon:
40 """
41 """
41 Methods that are identical for both implementations of the dirstatemap
42 Methods that are identical for both implementations of the dirstatemap
42 class, with and without Rust extensions enabled.
43 class, with and without Rust extensions enabled.
43 """
44 """
44
45
45 # please pytype
46 # please pytype
46
47
47 _map = None
48 _map = None
48 copymap = None
49 copymap = None
49
50
50 def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2):
51 def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2):
51 self._use_dirstate_v2 = use_dirstate_v2
52 self._use_dirstate_v2 = use_dirstate_v2
52 self._nodeconstants = nodeconstants
53 self._nodeconstants = nodeconstants
53 self._ui = ui
54 self._ui = ui
54 self._opener = opener
55 self._opener = opener
55 self._root = root
56 self._root = root
56 self._filename = b'dirstate'
57 self._filename = b'dirstate'
57 self._nodelen = 20 # Also update Rust code when changing this!
58 self._nodelen = 20 # Also update Rust code when changing this!
58 self._parents = None
59 self._parents = None
59 self._dirtyparents = False
60 self._dirtyparents = False
60 self._docket = None
61 self._docket = None
61 write_mode = ui.config(b"devel", b"dirstate.v2.data_update_mode")
62 write_mode = ui.config(b"devel", b"dirstate.v2.data_update_mode")
62 if write_mode == b"auto":
63 if write_mode == b"auto":
63 self._write_mode = WRITE_MODE_AUTO
64 self._write_mode = WRITE_MODE_AUTO
64 elif write_mode == b"force-append":
65 elif write_mode == b"force-append":
65 self._write_mode = WRITE_MODE_FORCE_APPEND
66 self._write_mode = WRITE_MODE_FORCE_APPEND
66 elif write_mode == b"force-new":
67 elif write_mode == b"force-new":
67 self._write_mode = WRITE_MODE_FORCE_NEW
68 self._write_mode = WRITE_MODE_FORCE_NEW
68 else:
69 else:
69 # unknown value, fallback to default
70 # unknown value, fallback to default
70 self._write_mode = WRITE_MODE_AUTO
71 self._write_mode = WRITE_MODE_AUTO
71
72
72 # for consistent view between _pl() and _read() invocations
73 # for consistent view between _pl() and _read() invocations
73 self._pendingmode = None
74 self._pendingmode = None
74
75
75 def preload(self):
76 def preload(self):
76 """Loads the underlying data, if it's not already loaded"""
77 """Loads the underlying data, if it's not already loaded"""
77 self._map
78 self._map
78
79
79 def get(self, key, default=None):
80 def get(self, key, default=None):
80 return self._map.get(key, default)
81 return self._map.get(key, default)
81
82
82 def __len__(self):
83 def __len__(self):
83 return len(self._map)
84 return len(self._map)
84
85
85 def __iter__(self):
86 def __iter__(self):
86 return iter(self._map)
87 return iter(self._map)
87
88
88 def __contains__(self, key):
89 def __contains__(self, key):
89 return key in self._map
90 return key in self._map
90
91
91 def __getitem__(self, item):
92 def __getitem__(self, item):
92 return self._map[item]
93 return self._map[item]
93
94
94 ### disk interaction
95 ### disk interaction
95
96
96 def _opendirstatefile(self):
97 def _opendirstatefile(self):
97 fp, mode = txnutil.trypending(self._root, self._opener, self._filename)
98 fp, mode = txnutil.trypending(self._root, self._opener, self._filename)
98 if self._pendingmode is not None and self._pendingmode != mode:
99 if self._pendingmode is not None and self._pendingmode != mode:
99 fp.close()
100 fp.close()
100 raise error.Abort(
101 raise error.Abort(
101 _(b'working directory state may be changed parallelly')
102 _(b'working directory state may be changed parallelly')
102 )
103 )
103 self._pendingmode = mode
104 self._pendingmode = mode
104 return fp
105 return fp
105
106
106 def _readdirstatefile(self, size=-1):
107 def _readdirstatefile(self, size=-1):
107 try:
108 try:
108 with self._opendirstatefile() as fp:
109 with self._opendirstatefile() as fp:
109 return fp.read(size)
110 return fp.read(size)
110 except FileNotFoundError:
111 except FileNotFoundError:
111 # File doesn't exist, so the current state is empty
112 # File doesn't exist, so the current state is empty
112 return b''
113 return b''
113
114
114 @property
115 @property
115 def docket(self):
116 def docket(self):
116 if not self._docket:
117 if not self._docket:
117 if not self._use_dirstate_v2:
118 if not self._use_dirstate_v2:
118 raise error.ProgrammingError(
119 raise error.ProgrammingError(
119 b'dirstate only has a docket in v2 format'
120 b'dirstate only has a docket in v2 format'
120 )
121 )
121 self._docket = docketmod.DirstateDocket.parse(
122 self._docket = docketmod.DirstateDocket.parse(
122 self._readdirstatefile(), self._nodeconstants
123 self._readdirstatefile(), self._nodeconstants
123 )
124 )
124 return self._docket
125 return self._docket
125
126
126 def write_v2_no_append(self, tr, st, meta, packed):
127 def write_v2_no_append(self, tr, st, meta, packed):
127 old_docket = self.docket
128 old_docket = self.docket
128 new_docket = docketmod.DirstateDocket.with_new_uuid(
129 new_docket = docketmod.DirstateDocket.with_new_uuid(
129 self.parents(), len(packed), meta
130 self.parents(), len(packed), meta
130 )
131 )
131 if old_docket.uuid == new_docket.uuid:
132 if old_docket.uuid == new_docket.uuid:
132 raise error.ProgrammingError(b'dirstate docket name collision')
133 raise error.ProgrammingError(b'dirstate docket name collision')
133 data_filename = new_docket.data_filename()
134 data_filename = new_docket.data_filename()
134 self._opener.write(data_filename, packed)
135 self._opener.write(data_filename, packed)
135 # Write the new docket after the new data file has been
136 # Write the new docket after the new data file has been
136 # written. Because `st` was opened with `atomictemp=True`,
137 # written. Because `st` was opened with `atomictemp=True`,
137 # the actual `.hg/dirstate` file is only affected on close.
138 # the actual `.hg/dirstate` file is only affected on close.
138 st.write(new_docket.serialize())
139 st.write(new_docket.serialize())
139 st.close()
140 st.close()
140 # Remove the old data file after the new docket pointing to
141 # Remove the old data file after the new docket pointing to
141 # the new data file was written.
142 # the new data file was written.
142 if old_docket.uuid:
143 if old_docket.uuid:
143 data_filename = old_docket.data_filename()
144 data_filename = old_docket.data_filename()
144 unlink = lambda _tr=None: self._opener.unlink(data_filename)
145 unlink = lambda _tr=None: self._opener.unlink(data_filename)
145 if tr:
146 if tr:
146 category = b"dirstate-v2-clean-" + old_docket.uuid
147 category = b"dirstate-v2-clean-" + old_docket.uuid
147 tr.addpostclose(category, unlink)
148 tr.addpostclose(category, unlink)
148 else:
149 else:
149 unlink()
150 unlink()
150 self._docket = new_docket
151 self._docket = new_docket
151
152
152 ### reading/setting parents
153 ### reading/setting parents
153
154
154 def parents(self):
155 def parents(self):
155 if not self._parents:
156 if not self._parents:
156 if self._use_dirstate_v2:
157 if self._use_dirstate_v2:
157 self._parents = self.docket.parents
158 self._parents = self.docket.parents
158 else:
159 else:
159 read_len = self._nodelen * 2
160 read_len = self._nodelen * 2
160 st = self._readdirstatefile(read_len)
161 st = self._readdirstatefile(read_len)
161 l = len(st)
162 l = len(st)
162 if l == read_len:
163 if l == read_len:
163 self._parents = (
164 self._parents = (
164 st[: self._nodelen],
165 st[: self._nodelen],
165 st[self._nodelen : 2 * self._nodelen],
166 st[self._nodelen : 2 * self._nodelen],
166 )
167 )
167 elif l == 0:
168 elif l == 0:
168 self._parents = (
169 self._parents = (
169 self._nodeconstants.nullid,
170 self._nodeconstants.nullid,
170 self._nodeconstants.nullid,
171 self._nodeconstants.nullid,
171 )
172 )
172 else:
173 else:
173 raise error.Abort(
174 raise error.Abort(
174 _(b'working directory state appears damaged!')
175 _(b'working directory state appears damaged!')
175 )
176 )
176
177
177 return self._parents
178 return self._parents
178
179
179
180
180 class dirstatemap(_dirstatemapcommon):
181 class dirstatemap(_dirstatemapcommon):
181 """Map encapsulating the dirstate's contents.
182 """Map encapsulating the dirstate's contents.
182
183
183 The dirstate contains the following state:
184 The dirstate contains the following state:
184
185
185 - `identity` is the identity of the dirstate file, which can be used to
186 - `identity` is the identity of the dirstate file, which can be used to
186 detect when changes have occurred to the dirstate file.
187 detect when changes have occurred to the dirstate file.
187
188
188 - `parents` is a pair containing the parents of the working copy. The
189 - `parents` is a pair containing the parents of the working copy. The
189 parents are updated by calling `setparents`.
190 parents are updated by calling `setparents`.
190
191
191 - the state map maps filenames to tuples of (state, mode, size, mtime),
192 - the state map maps filenames to tuples of (state, mode, size, mtime),
192 where state is a single character representing 'normal', 'added',
193 where state is a single character representing 'normal', 'added',
193 'removed', or 'merged'. It is read by treating the dirstate as a
194 'removed', or 'merged'. It is read by treating the dirstate as a
194 dict. File state is updated by calling various methods (see each
195 dict. File state is updated by calling various methods (see each
195 documentation for details):
196 documentation for details):
196
197
197 - `reset_state`,
198 - `reset_state`,
198 - `set_tracked`
199 - `set_tracked`
199 - `set_untracked`
200 - `set_untracked`
200 - `set_clean`
201 - `set_clean`
201 - `set_possibly_dirty`
202 - `set_possibly_dirty`
202
203
203 - `copymap` maps destination filenames to their source filename.
204 - `copymap` maps destination filenames to their source filename.
204
205
205 The dirstate also provides the following views onto the state:
206 The dirstate also provides the following views onto the state:
206
207
207 - `filefoldmap` is a dict mapping normalized filenames to the denormalized
208 - `filefoldmap` is a dict mapping normalized filenames to the denormalized
208 form that they appear as in the dirstate.
209 form that they appear as in the dirstate.
209
210
210 - `dirfoldmap` is a dict mapping normalized directory names to the
211 - `dirfoldmap` is a dict mapping normalized directory names to the
211 denormalized form that they appear as in the dirstate.
212 denormalized form that they appear as in the dirstate.
212 """
213 """
213
214
214 ### Core data storage and access
215 ### Core data storage and access
215
216
216 @propertycache
217 @propertycache
217 def _map(self):
218 def _map(self):
218 self._map = {}
219 self._map = {}
219 self.read()
220 self.read()
220 return self._map
221 return self._map
221
222
222 @propertycache
223 @propertycache
223 def copymap(self):
224 def copymap(self):
224 self.copymap = {}
225 self.copymap = {}
225 self._map
226 self._map
226 return self.copymap
227 return self.copymap
227
228
228 def clear(self):
229 def clear(self):
229 self._map.clear()
230 self._map.clear()
230 self.copymap.clear()
231 self.copymap.clear()
231 self.setparents(self._nodeconstants.nullid, self._nodeconstants.nullid)
232 self.setparents(self._nodeconstants.nullid, self._nodeconstants.nullid)
232 util.clearcachedproperty(self, b"_dirs")
233 util.clearcachedproperty(self, b"_dirs")
233 util.clearcachedproperty(self, b"_alldirs")
234 util.clearcachedproperty(self, b"_alldirs")
234 util.clearcachedproperty(self, b"filefoldmap")
235 util.clearcachedproperty(self, b"filefoldmap")
235 util.clearcachedproperty(self, b"dirfoldmap")
236 util.clearcachedproperty(self, b"dirfoldmap")
236
237
237 def items(self):
238 def items(self):
238 return self._map.items()
239 return self._map.items()
239
240
240 # forward for python2,3 compat
241 # forward for python2,3 compat
241 iteritems = items
242 iteritems = items
242
243
243 def debug_iter(self, all):
244 def debug_iter(self, all):
244 """
245 """
245 Return an iterator of (filename, state, mode, size, mtime) tuples
246 Return an iterator of (filename, state, mode, size, mtime) tuples
246
247
247 `all` is unused when Rust is not enabled
248 `all` is unused when Rust is not enabled
248 """
249 """
249 for (filename, item) in self.items():
250 for (filename, item) in self.items():
250 yield (filename, item.state, item.mode, item.size, item.mtime)
251 yield (filename, item.state, item.mode, item.size, item.mtime)
251
252
252 def keys(self):
253 def keys(self):
253 return self._map.keys()
254 return self._map.keys()
254
255
255 ### reading/setting parents
256 ### reading/setting parents
256
257
257 def setparents(self, p1, p2, fold_p2=False):
258 def setparents(self, p1, p2, fold_p2=False):
258 self._parents = (p1, p2)
259 self._parents = (p1, p2)
259 self._dirtyparents = True
260 self._dirtyparents = True
260 copies = {}
261 copies = {}
261 if fold_p2:
262 if fold_p2:
262 for f, s in self._map.items():
263 for f, s in self._map.items():
263 # Discard "merged" markers when moving away from a merge state
264 # Discard "merged" markers when moving away from a merge state
264 if s.p2_info:
265 if s.p2_info:
265 source = self.copymap.pop(f, None)
266 source = self.copymap.pop(f, None)
266 if source:
267 if source:
267 copies[f] = source
268 copies[f] = source
268 s.drop_merge_data()
269 s.drop_merge_data()
269 return copies
270 return copies
270
271
271 ### disk interaction
272 ### disk interaction
272
273
273 def read(self):
274 def read(self):
274 # ignore HG_PENDING because identity is used only for writing
275 # ignore HG_PENDING because identity is used only for writing
275 self.identity = util.filestat.frompath(
276 self.identity = util.filestat.frompath(
276 self._opener.join(self._filename)
277 self._opener.join(self._filename)
277 )
278 )
278
279
280 testing.wait_on_cfg(self._ui, b'dirstate.pre-read-file')
279 if self._use_dirstate_v2:
281 if self._use_dirstate_v2:
282
280 if not self.docket.uuid:
283 if not self.docket.uuid:
281 return
284 return
282 st = self._opener.read(self.docket.data_filename())
285 st = self._opener.read(self.docket.data_filename())
283 else:
286 else:
284 st = self._readdirstatefile()
287 st = self._readdirstatefile()
285
288
286 if not st:
289 if not st:
287 return
290 return
288
291
289 # TODO: adjust this estimate for dirstate-v2
292 # TODO: adjust this estimate for dirstate-v2
290 if util.safehasattr(parsers, b'dict_new_presized'):
293 if util.safehasattr(parsers, b'dict_new_presized'):
291 # Make an estimate of the number of files in the dirstate based on
294 # Make an estimate of the number of files in the dirstate based on
292 # its size. This trades wasting some memory for avoiding costly
295 # its size. This trades wasting some memory for avoiding costly
293 # resizes. Each entry have a prefix of 17 bytes followed by one or
296 # resizes. Each entry have a prefix of 17 bytes followed by one or
294 # two path names. Studies on various large-scale real-world repositories
297 # two path names. Studies on various large-scale real-world repositories
295 # found 54 bytes a reasonable upper limit for the average path names.
298 # found 54 bytes a reasonable upper limit for the average path names.
296 # Copy entries are ignored for the sake of this estimate.
299 # Copy entries are ignored for the sake of this estimate.
297 self._map = parsers.dict_new_presized(len(st) // 71)
300 self._map = parsers.dict_new_presized(len(st) // 71)
298
301
299 # Python's garbage collector triggers a GC each time a certain number
302 # Python's garbage collector triggers a GC each time a certain number
300 # of container objects (the number being defined by
303 # of container objects (the number being defined by
301 # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
304 # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
302 # for each file in the dirstate. The C version then immediately marks
305 # for each file in the dirstate. The C version then immediately marks
303 # them as not to be tracked by the collector. However, this has no
306 # them as not to be tracked by the collector. However, this has no
304 # effect on when GCs are triggered, only on what objects the GC looks
307 # effect on when GCs are triggered, only on what objects the GC looks
305 # into. This means that O(number of files) GCs are unavoidable.
308 # into. This means that O(number of files) GCs are unavoidable.
306 # Depending on when in the process's lifetime the dirstate is parsed,
309 # Depending on when in the process's lifetime the dirstate is parsed,
307 # this can get very expensive. As a workaround, disable GC while
310 # this can get very expensive. As a workaround, disable GC while
308 # parsing the dirstate.
311 # parsing the dirstate.
309 #
312 #
310 # (we cannot decorate the function directly since it is in a C module)
313 # (we cannot decorate the function directly since it is in a C module)
311 if self._use_dirstate_v2:
314 if self._use_dirstate_v2:
312 p = self.docket.parents
315 p = self.docket.parents
313 meta = self.docket.tree_metadata
316 meta = self.docket.tree_metadata
314 parse_dirstate = util.nogc(v2.parse_dirstate)
317 parse_dirstate = util.nogc(v2.parse_dirstate)
315 parse_dirstate(self._map, self.copymap, st, meta)
318 parse_dirstate(self._map, self.copymap, st, meta)
316 else:
319 else:
317 parse_dirstate = util.nogc(parsers.parse_dirstate)
320 parse_dirstate = util.nogc(parsers.parse_dirstate)
318 p = parse_dirstate(self._map, self.copymap, st)
321 p = parse_dirstate(self._map, self.copymap, st)
319 if not self._dirtyparents:
322 if not self._dirtyparents:
320 self.setparents(*p)
323 self.setparents(*p)
321
324
322 # Avoid excess attribute lookups by fast pathing certain checks
325 # Avoid excess attribute lookups by fast pathing certain checks
323 self.__contains__ = self._map.__contains__
326 self.__contains__ = self._map.__contains__
324 self.__getitem__ = self._map.__getitem__
327 self.__getitem__ = self._map.__getitem__
325 self.get = self._map.get
328 self.get = self._map.get
326
329
327 def write(self, tr, st):
330 def write(self, tr, st):
328 if self._use_dirstate_v2:
331 if self._use_dirstate_v2:
329 packed, meta = v2.pack_dirstate(self._map, self.copymap)
332 packed, meta = v2.pack_dirstate(self._map, self.copymap)
330 self.write_v2_no_append(tr, st, meta, packed)
333 self.write_v2_no_append(tr, st, meta, packed)
331 else:
334 else:
332 packed = parsers.pack_dirstate(
335 packed = parsers.pack_dirstate(
333 self._map, self.copymap, self.parents()
336 self._map, self.copymap, self.parents()
334 )
337 )
335 st.write(packed)
338 st.write(packed)
336 st.close()
339 st.close()
337 self._dirtyparents = False
340 self._dirtyparents = False
338
341
339 @propertycache
342 @propertycache
340 def identity(self):
343 def identity(self):
341 self._map
344 self._map
342 return self.identity
345 return self.identity
343
346
344 ### code related to maintaining and accessing "extra" property
347 ### code related to maintaining and accessing "extra" property
345 # (e.g. "has_dir")
348 # (e.g. "has_dir")
346
349
347 def _dirs_incr(self, filename, old_entry=None):
350 def _dirs_incr(self, filename, old_entry=None):
348 """increment the dirstate counter if applicable"""
351 """increment the dirstate counter if applicable"""
349 if (
352 if (
350 old_entry is None or old_entry.removed
353 old_entry is None or old_entry.removed
351 ) and "_dirs" in self.__dict__:
354 ) and "_dirs" in self.__dict__:
352 self._dirs.addpath(filename)
355 self._dirs.addpath(filename)
353 if old_entry is None and "_alldirs" in self.__dict__:
356 if old_entry is None and "_alldirs" in self.__dict__:
354 self._alldirs.addpath(filename)
357 self._alldirs.addpath(filename)
355
358
356 def _dirs_decr(self, filename, old_entry=None, remove_variant=False):
359 def _dirs_decr(self, filename, old_entry=None, remove_variant=False):
357 """decrement the dirstate counter if applicable"""
360 """decrement the dirstate counter if applicable"""
358 if old_entry is not None:
361 if old_entry is not None:
359 if "_dirs" in self.__dict__ and not old_entry.removed:
362 if "_dirs" in self.__dict__ and not old_entry.removed:
360 self._dirs.delpath(filename)
363 self._dirs.delpath(filename)
361 if "_alldirs" in self.__dict__ and not remove_variant:
364 if "_alldirs" in self.__dict__ and not remove_variant:
362 self._alldirs.delpath(filename)
365 self._alldirs.delpath(filename)
363 elif remove_variant and "_alldirs" in self.__dict__:
366 elif remove_variant and "_alldirs" in self.__dict__:
364 self._alldirs.addpath(filename)
367 self._alldirs.addpath(filename)
365 if "filefoldmap" in self.__dict__:
368 if "filefoldmap" in self.__dict__:
366 normed = util.normcase(filename)
369 normed = util.normcase(filename)
367 self.filefoldmap.pop(normed, None)
370 self.filefoldmap.pop(normed, None)
368
371
369 @propertycache
372 @propertycache
370 def filefoldmap(self):
373 def filefoldmap(self):
371 """Returns a dictionary mapping normalized case paths to their
374 """Returns a dictionary mapping normalized case paths to their
372 non-normalized versions.
375 non-normalized versions.
373 """
376 """
374 try:
377 try:
375 makefilefoldmap = parsers.make_file_foldmap
378 makefilefoldmap = parsers.make_file_foldmap
376 except AttributeError:
379 except AttributeError:
377 pass
380 pass
378 else:
381 else:
379 return makefilefoldmap(
382 return makefilefoldmap(
380 self._map, util.normcasespec, util.normcasefallback
383 self._map, util.normcasespec, util.normcasefallback
381 )
384 )
382
385
383 f = {}
386 f = {}
384 normcase = util.normcase
387 normcase = util.normcase
385 for name, s in self._map.items():
388 for name, s in self._map.items():
386 if not s.removed:
389 if not s.removed:
387 f[normcase(name)] = name
390 f[normcase(name)] = name
388 f[b'.'] = b'.' # prevents useless util.fspath() invocation
391 f[b'.'] = b'.' # prevents useless util.fspath() invocation
389 return f
392 return f
390
393
391 @propertycache
394 @propertycache
392 def dirfoldmap(self):
395 def dirfoldmap(self):
393 f = {}
396 f = {}
394 normcase = util.normcase
397 normcase = util.normcase
395 for name in self._dirs:
398 for name in self._dirs:
396 f[normcase(name)] = name
399 f[normcase(name)] = name
397 return f
400 return f
398
401
399 def hastrackeddir(self, d):
402 def hastrackeddir(self, d):
400 """
403 """
401 Returns True if the dirstate contains a tracked (not removed) file
404 Returns True if the dirstate contains a tracked (not removed) file
402 in this directory.
405 in this directory.
403 """
406 """
404 return d in self._dirs
407 return d in self._dirs
405
408
406 def hasdir(self, d):
409 def hasdir(self, d):
407 """
410 """
408 Returns True if the dirstate contains a file (tracked or removed)
411 Returns True if the dirstate contains a file (tracked or removed)
409 in this directory.
412 in this directory.
410 """
413 """
411 return d in self._alldirs
414 return d in self._alldirs
412
415
413 @propertycache
416 @propertycache
414 def _dirs(self):
417 def _dirs(self):
415 return pathutil.dirs(self._map, only_tracked=True)
418 return pathutil.dirs(self._map, only_tracked=True)
416
419
417 @propertycache
420 @propertycache
418 def _alldirs(self):
421 def _alldirs(self):
419 return pathutil.dirs(self._map)
422 return pathutil.dirs(self._map)
420
423
421 ### code related to manipulation of entries and copy-sources
424 ### code related to manipulation of entries and copy-sources
422
425
423 def reset_state(
426 def reset_state(
424 self,
427 self,
425 filename,
428 filename,
426 wc_tracked=False,
429 wc_tracked=False,
427 p1_tracked=False,
430 p1_tracked=False,
428 p2_info=False,
431 p2_info=False,
429 has_meaningful_mtime=True,
432 has_meaningful_mtime=True,
430 parentfiledata=None,
433 parentfiledata=None,
431 ):
434 ):
432 """Set a entry to a given state, diregarding all previous state
435 """Set a entry to a given state, diregarding all previous state
433
436
434 This is to be used by the part of the dirstate API dedicated to
437 This is to be used by the part of the dirstate API dedicated to
435 adjusting the dirstate after a update/merge.
438 adjusting the dirstate after a update/merge.
436
439
437 note: calling this might result to no entry existing at all if the
440 note: calling this might result to no entry existing at all if the
438 dirstate map does not see any point at having one for this file
441 dirstate map does not see any point at having one for this file
439 anymore.
442 anymore.
440 """
443 """
441 # copy information are now outdated
444 # copy information are now outdated
442 # (maybe new information should be in directly passed to this function)
445 # (maybe new information should be in directly passed to this function)
443 self.copymap.pop(filename, None)
446 self.copymap.pop(filename, None)
444
447
445 if not (p1_tracked or p2_info or wc_tracked):
448 if not (p1_tracked or p2_info or wc_tracked):
446 old_entry = self._map.get(filename)
449 old_entry = self._map.get(filename)
447 self._drop_entry(filename)
450 self._drop_entry(filename)
448 self._dirs_decr(filename, old_entry=old_entry)
451 self._dirs_decr(filename, old_entry=old_entry)
449 return
452 return
450
453
451 old_entry = self._map.get(filename)
454 old_entry = self._map.get(filename)
452 self._dirs_incr(filename, old_entry)
455 self._dirs_incr(filename, old_entry)
453 entry = DirstateItem(
456 entry = DirstateItem(
454 wc_tracked=wc_tracked,
457 wc_tracked=wc_tracked,
455 p1_tracked=p1_tracked,
458 p1_tracked=p1_tracked,
456 p2_info=p2_info,
459 p2_info=p2_info,
457 has_meaningful_mtime=has_meaningful_mtime,
460 has_meaningful_mtime=has_meaningful_mtime,
458 parentfiledata=parentfiledata,
461 parentfiledata=parentfiledata,
459 )
462 )
460 self._map[filename] = entry
463 self._map[filename] = entry
461
464
462 def set_tracked(self, filename):
465 def set_tracked(self, filename):
463 new = False
466 new = False
464 entry = self.get(filename)
467 entry = self.get(filename)
465 if entry is None:
468 if entry is None:
466 self._dirs_incr(filename)
469 self._dirs_incr(filename)
467 entry = DirstateItem(
470 entry = DirstateItem(
468 wc_tracked=True,
471 wc_tracked=True,
469 )
472 )
470
473
471 self._map[filename] = entry
474 self._map[filename] = entry
472 new = True
475 new = True
473 elif not entry.tracked:
476 elif not entry.tracked:
474 self._dirs_incr(filename, entry)
477 self._dirs_incr(filename, entry)
475 entry.set_tracked()
478 entry.set_tracked()
476 self._refresh_entry(filename, entry)
479 self._refresh_entry(filename, entry)
477 new = True
480 new = True
478 else:
481 else:
479 # XXX This is probably overkill for more case, but we need this to
482 # XXX This is probably overkill for more case, but we need this to
480 # fully replace the `normallookup` call with `set_tracked` one.
483 # fully replace the `normallookup` call with `set_tracked` one.
481 # Consider smoothing this in the future.
484 # Consider smoothing this in the future.
482 entry.set_possibly_dirty()
485 entry.set_possibly_dirty()
483 self._refresh_entry(filename, entry)
486 self._refresh_entry(filename, entry)
484 return new
487 return new
485
488
486 def set_untracked(self, f):
489 def set_untracked(self, f):
487 """Mark a file as no longer tracked in the dirstate map"""
490 """Mark a file as no longer tracked in the dirstate map"""
488 entry = self.get(f)
491 entry = self.get(f)
489 if entry is None:
492 if entry is None:
490 return False
493 return False
491 else:
494 else:
492 self._dirs_decr(f, old_entry=entry, remove_variant=not entry.added)
495 self._dirs_decr(f, old_entry=entry, remove_variant=not entry.added)
493 if not entry.p2_info:
496 if not entry.p2_info:
494 self.copymap.pop(f, None)
497 self.copymap.pop(f, None)
495 entry.set_untracked()
498 entry.set_untracked()
496 self._refresh_entry(f, entry)
499 self._refresh_entry(f, entry)
497 return True
500 return True
498
501
499 def set_clean(self, filename, mode, size, mtime):
502 def set_clean(self, filename, mode, size, mtime):
500 """mark a file as back to a clean state"""
503 """mark a file as back to a clean state"""
501 entry = self[filename]
504 entry = self[filename]
502 size = size & rangemask
505 size = size & rangemask
503 entry.set_clean(mode, size, mtime)
506 entry.set_clean(mode, size, mtime)
504 self._refresh_entry(filename, entry)
507 self._refresh_entry(filename, entry)
505 self.copymap.pop(filename, None)
508 self.copymap.pop(filename, None)
506
509
507 def set_possibly_dirty(self, filename):
510 def set_possibly_dirty(self, filename):
508 """record that the current state of the file on disk is unknown"""
511 """record that the current state of the file on disk is unknown"""
509 entry = self[filename]
512 entry = self[filename]
510 entry.set_possibly_dirty()
513 entry.set_possibly_dirty()
511 self._refresh_entry(filename, entry)
514 self._refresh_entry(filename, entry)
512
515
513 def _refresh_entry(self, f, entry):
516 def _refresh_entry(self, f, entry):
514 """record updated state of an entry"""
517 """record updated state of an entry"""
515 if not entry.any_tracked:
518 if not entry.any_tracked:
516 self._map.pop(f, None)
519 self._map.pop(f, None)
517
520
518 def _drop_entry(self, f):
521 def _drop_entry(self, f):
519 """remove any entry for file f
522 """remove any entry for file f
520
523
521 This should also drop associated copy information
524 This should also drop associated copy information
522
525
523 The fact we actually need to drop it is the responsability of the caller"""
526 The fact we actually need to drop it is the responsability of the caller"""
524 self._map.pop(f, None)
527 self._map.pop(f, None)
525 self.copymap.pop(f, None)
528 self.copymap.pop(f, None)
526
529
527
530
528 if rustmod is not None:
531 if rustmod is not None:
529
532
530 class dirstatemap(_dirstatemapcommon):
533 class dirstatemap(_dirstatemapcommon):
531
534
532 ### Core data storage and access
535 ### Core data storage and access
533
536
534 @propertycache
537 @propertycache
535 def _map(self):
538 def _map(self):
536 """
539 """
537 Fills the Dirstatemap when called.
540 Fills the Dirstatemap when called.
538 """
541 """
539 # ignore HG_PENDING because identity is used only for writing
542 # ignore HG_PENDING because identity is used only for writing
540 self.identity = util.filestat.frompath(
543 self.identity = util.filestat.frompath(
541 self._opener.join(self._filename)
544 self._opener.join(self._filename)
542 )
545 )
543
546
547 testing.wait_on_cfg(self._ui, b'dirstate.pre-read-file')
544 if self._use_dirstate_v2:
548 if self._use_dirstate_v2:
545 if self.docket.uuid:
549 if self.docket.uuid:
546 # TODO: use mmap when possible
550 # TODO: use mmap when possible
547 data = self._opener.read(self.docket.data_filename())
551 data = self._opener.read(self.docket.data_filename())
548 else:
552 else:
549 data = b''
553 data = b''
550 self._map = rustmod.DirstateMap.new_v2(
554 self._map = rustmod.DirstateMap.new_v2(
551 data, self.docket.data_size, self.docket.tree_metadata
555 data, self.docket.data_size, self.docket.tree_metadata
552 )
556 )
553 parents = self.docket.parents
557 parents = self.docket.parents
554 else:
558 else:
555 self._map, parents = rustmod.DirstateMap.new_v1(
559 self._map, parents = rustmod.DirstateMap.new_v1(
556 self._readdirstatefile()
560 self._readdirstatefile()
557 )
561 )
558
562
559 if parents and not self._dirtyparents:
563 if parents and not self._dirtyparents:
560 self.setparents(*parents)
564 self.setparents(*parents)
561
565
562 self.__contains__ = self._map.__contains__
566 self.__contains__ = self._map.__contains__
563 self.__getitem__ = self._map.__getitem__
567 self.__getitem__ = self._map.__getitem__
564 self.get = self._map.get
568 self.get = self._map.get
565 return self._map
569 return self._map
566
570
567 @property
571 @property
568 def copymap(self):
572 def copymap(self):
569 return self._map.copymap()
573 return self._map.copymap()
570
574
571 def debug_iter(self, all):
575 def debug_iter(self, all):
572 """
576 """
573 Return an iterator of (filename, state, mode, size, mtime) tuples
577 Return an iterator of (filename, state, mode, size, mtime) tuples
574
578
575 `all`: also include with `state == b' '` dirstate tree nodes that
579 `all`: also include with `state == b' '` dirstate tree nodes that
576 don't have an associated `DirstateItem`.
580 don't have an associated `DirstateItem`.
577
581
578 """
582 """
579 return self._map.debug_iter(all)
583 return self._map.debug_iter(all)
580
584
581 def clear(self):
585 def clear(self):
582 self._map.clear()
586 self._map.clear()
583 self.setparents(
587 self.setparents(
584 self._nodeconstants.nullid, self._nodeconstants.nullid
588 self._nodeconstants.nullid, self._nodeconstants.nullid
585 )
589 )
586 util.clearcachedproperty(self, b"_dirs")
590 util.clearcachedproperty(self, b"_dirs")
587 util.clearcachedproperty(self, b"_alldirs")
591 util.clearcachedproperty(self, b"_alldirs")
588 util.clearcachedproperty(self, b"dirfoldmap")
592 util.clearcachedproperty(self, b"dirfoldmap")
589
593
590 def items(self):
594 def items(self):
591 return self._map.items()
595 return self._map.items()
592
596
593 # forward for python2,3 compat
597 # forward for python2,3 compat
594 iteritems = items
598 iteritems = items
595
599
596 def keys(self):
600 def keys(self):
597 return iter(self._map)
601 return iter(self._map)
598
602
599 ### reading/setting parents
603 ### reading/setting parents
600
604
601 def setparents(self, p1, p2, fold_p2=False):
605 def setparents(self, p1, p2, fold_p2=False):
602 self._parents = (p1, p2)
606 self._parents = (p1, p2)
603 self._dirtyparents = True
607 self._dirtyparents = True
604 copies = {}
608 copies = {}
605 if fold_p2:
609 if fold_p2:
606 copies = self._map.setparents_fixup()
610 copies = self._map.setparents_fixup()
607 return copies
611 return copies
608
612
609 ### disk interaction
613 ### disk interaction
610
614
611 @propertycache
615 @propertycache
612 def identity(self):
616 def identity(self):
613 self._map
617 self._map
614 return self.identity
618 return self.identity
615
619
616 def write(self, tr, st):
620 def write(self, tr, st):
617 if not self._use_dirstate_v2:
621 if not self._use_dirstate_v2:
618 p1, p2 = self.parents()
622 p1, p2 = self.parents()
619 packed = self._map.write_v1(p1, p2)
623 packed = self._map.write_v1(p1, p2)
620 st.write(packed)
624 st.write(packed)
621 st.close()
625 st.close()
622 self._dirtyparents = False
626 self._dirtyparents = False
623 return
627 return
624
628
625 # We can only append to an existing data file if there is one
629 # We can only append to an existing data file if there is one
626 write_mode = self._write_mode
630 write_mode = self._write_mode
627 if self.docket.uuid is None:
631 if self.docket.uuid is None:
628 write_mode = WRITE_MODE_FORCE_NEW
632 write_mode = WRITE_MODE_FORCE_NEW
629 packed, meta, append = self._map.write_v2(write_mode)
633 packed, meta, append = self._map.write_v2(write_mode)
630 if append:
634 if append:
631 docket = self.docket
635 docket = self.docket
632 data_filename = docket.data_filename()
636 data_filename = docket.data_filename()
633 with self._opener(data_filename, b'r+b') as fp:
637 with self._opener(data_filename, b'r+b') as fp:
634 fp.seek(docket.data_size)
638 fp.seek(docket.data_size)
635 assert fp.tell() == docket.data_size
639 assert fp.tell() == docket.data_size
636 written = fp.write(packed)
640 written = fp.write(packed)
637 if written is not None: # py2 may return None
641 if written is not None: # py2 may return None
638 assert written == len(packed), (written, len(packed))
642 assert written == len(packed), (written, len(packed))
639 docket.data_size += len(packed)
643 docket.data_size += len(packed)
640 docket.parents = self.parents()
644 docket.parents = self.parents()
641 docket.tree_metadata = meta
645 docket.tree_metadata = meta
642 st.write(docket.serialize())
646 st.write(docket.serialize())
643 st.close()
647 st.close()
644 else:
648 else:
645 self.write_v2_no_append(tr, st, meta, packed)
649 self.write_v2_no_append(tr, st, meta, packed)
646 # Reload from the newly-written file
650 # Reload from the newly-written file
647 util.clearcachedproperty(self, b"_map")
651 util.clearcachedproperty(self, b"_map")
648 self._dirtyparents = False
652 self._dirtyparents = False
649
653
650 ### code related to maintaining and accessing "extra" property
654 ### code related to maintaining and accessing "extra" property
651 # (e.g. "has_dir")
655 # (e.g. "has_dir")
652
656
653 @propertycache
657 @propertycache
654 def filefoldmap(self):
658 def filefoldmap(self):
655 """Returns a dictionary mapping normalized case paths to their
659 """Returns a dictionary mapping normalized case paths to their
656 non-normalized versions.
660 non-normalized versions.
657 """
661 """
658 return self._map.filefoldmapasdict()
662 return self._map.filefoldmapasdict()
659
663
660 def hastrackeddir(self, d):
664 def hastrackeddir(self, d):
661 return self._map.hastrackeddir(d)
665 return self._map.hastrackeddir(d)
662
666
663 def hasdir(self, d):
667 def hasdir(self, d):
664 return self._map.hasdir(d)
668 return self._map.hasdir(d)
665
669
666 @propertycache
670 @propertycache
667 def dirfoldmap(self):
671 def dirfoldmap(self):
668 f = {}
672 f = {}
669 normcase = util.normcase
673 normcase = util.normcase
670 for name in self._map.tracked_dirs():
674 for name in self._map.tracked_dirs():
671 f[normcase(name)] = name
675 f[normcase(name)] = name
672 return f
676 return f
673
677
674 ### code related to manipulation of entries and copy-sources
678 ### code related to manipulation of entries and copy-sources
675
679
676 def set_tracked(self, f):
680 def set_tracked(self, f):
677 return self._map.set_tracked(f)
681 return self._map.set_tracked(f)
678
682
679 def set_untracked(self, f):
683 def set_untracked(self, f):
680 return self._map.set_untracked(f)
684 return self._map.set_untracked(f)
681
685
682 def set_clean(self, filename, mode, size, mtime):
686 def set_clean(self, filename, mode, size, mtime):
683 self._map.set_clean(filename, mode, size, mtime)
687 self._map.set_clean(filename, mode, size, mtime)
684
688
685 def set_possibly_dirty(self, f):
689 def set_possibly_dirty(self, f):
686 self._map.set_possibly_dirty(f)
690 self._map.set_possibly_dirty(f)
687
691
688 def reset_state(
692 def reset_state(
689 self,
693 self,
690 filename,
694 filename,
691 wc_tracked=False,
695 wc_tracked=False,
692 p1_tracked=False,
696 p1_tracked=False,
693 p2_info=False,
697 p2_info=False,
694 has_meaningful_mtime=True,
698 has_meaningful_mtime=True,
695 parentfiledata=None,
699 parentfiledata=None,
696 ):
700 ):
697 return self._map.reset_state(
701 return self._map.reset_state(
698 filename,
702 filename,
699 wc_tracked,
703 wc_tracked,
700 p1_tracked,
704 p1_tracked,
701 p2_info,
705 p2_info,
702 has_meaningful_mtime,
706 has_meaningful_mtime,
703 parentfiledata,
707 parentfiledata,
704 )
708 )
@@ -1,609 +1,615 b''
1 use crate::changelog::Changelog;
1 use crate::changelog::Changelog;
2 use crate::config::{Config, ConfigError, ConfigParseError};
2 use crate::config::{Config, ConfigError, ConfigParseError};
3 use crate::dirstate::DirstateParents;
3 use crate::dirstate::DirstateParents;
4 use crate::dirstate_tree::dirstate_map::DirstateMapWriteMode;
4 use crate::dirstate_tree::dirstate_map::DirstateMapWriteMode;
5 use crate::dirstate_tree::on_disk::Docket as DirstateDocket;
5 use crate::dirstate_tree::on_disk::Docket as DirstateDocket;
6 use crate::dirstate_tree::owning::OwningDirstateMap;
6 use crate::dirstate_tree::owning::OwningDirstateMap;
7 use crate::errors::HgResultExt;
7 use crate::errors::HgResultExt;
8 use crate::errors::{HgError, IoResultExt};
8 use crate::errors::{HgError, IoResultExt};
9 use crate::lock::{try_with_lock_no_wait, LockError};
9 use crate::lock::{try_with_lock_no_wait, LockError};
10 use crate::manifest::{Manifest, Manifestlog};
10 use crate::manifest::{Manifest, Manifestlog};
11 use crate::revlog::filelog::Filelog;
11 use crate::revlog::filelog::Filelog;
12 use crate::revlog::revlog::RevlogError;
12 use crate::revlog::revlog::RevlogError;
13 use crate::utils::debug::debug_wait_for_file_or_print;
13 use crate::utils::files::get_path_from_bytes;
14 use crate::utils::files::get_path_from_bytes;
14 use crate::utils::hg_path::HgPath;
15 use crate::utils::hg_path::HgPath;
15 use crate::utils::SliceExt;
16 use crate::utils::SliceExt;
16 use crate::vfs::{is_dir, is_file, Vfs};
17 use crate::vfs::{is_dir, is_file, Vfs};
17 use crate::{requirements, NodePrefix};
18 use crate::{requirements, NodePrefix};
18 use crate::{DirstateError, Revision};
19 use crate::{DirstateError, Revision};
19 use std::cell::{Ref, RefCell, RefMut};
20 use std::cell::{Ref, RefCell, RefMut};
20 use std::collections::HashSet;
21 use std::collections::HashSet;
21 use std::io::Seek;
22 use std::io::Seek;
22 use std::io::SeekFrom;
23 use std::io::SeekFrom;
23 use std::io::Write as IoWrite;
24 use std::io::Write as IoWrite;
24 use std::path::{Path, PathBuf};
25 use std::path::{Path, PathBuf};
25
26
26 /// A repository on disk
27 /// A repository on disk
27 pub struct Repo {
28 pub struct Repo {
28 working_directory: PathBuf,
29 working_directory: PathBuf,
29 dot_hg: PathBuf,
30 dot_hg: PathBuf,
30 store: PathBuf,
31 store: PathBuf,
31 requirements: HashSet<String>,
32 requirements: HashSet<String>,
32 config: Config,
33 config: Config,
33 dirstate_parents: LazyCell<DirstateParents>,
34 dirstate_parents: LazyCell<DirstateParents>,
34 dirstate_data_file_uuid: LazyCell<Option<Vec<u8>>>,
35 dirstate_data_file_uuid: LazyCell<Option<Vec<u8>>>,
35 dirstate_map: LazyCell<OwningDirstateMap>,
36 dirstate_map: LazyCell<OwningDirstateMap>,
36 changelog: LazyCell<Changelog>,
37 changelog: LazyCell<Changelog>,
37 manifestlog: LazyCell<Manifestlog>,
38 manifestlog: LazyCell<Manifestlog>,
38 }
39 }
39
40
40 #[derive(Debug, derive_more::From)]
41 #[derive(Debug, derive_more::From)]
41 pub enum RepoError {
42 pub enum RepoError {
42 NotFound {
43 NotFound {
43 at: PathBuf,
44 at: PathBuf,
44 },
45 },
45 #[from]
46 #[from]
46 ConfigParseError(ConfigParseError),
47 ConfigParseError(ConfigParseError),
47 #[from]
48 #[from]
48 Other(HgError),
49 Other(HgError),
49 }
50 }
50
51
51 impl From<ConfigError> for RepoError {
52 impl From<ConfigError> for RepoError {
52 fn from(error: ConfigError) -> Self {
53 fn from(error: ConfigError) -> Self {
53 match error {
54 match error {
54 ConfigError::Parse(error) => error.into(),
55 ConfigError::Parse(error) => error.into(),
55 ConfigError::Other(error) => error.into(),
56 ConfigError::Other(error) => error.into(),
56 }
57 }
57 }
58 }
58 }
59 }
59
60
60 impl Repo {
61 impl Repo {
61 /// tries to find nearest repository root in current working directory or
62 /// tries to find nearest repository root in current working directory or
62 /// its ancestors
63 /// its ancestors
63 pub fn find_repo_root() -> Result<PathBuf, RepoError> {
64 pub fn find_repo_root() -> Result<PathBuf, RepoError> {
64 let current_directory = crate::utils::current_dir()?;
65 let current_directory = crate::utils::current_dir()?;
65 // ancestors() is inclusive: it first yields `current_directory`
66 // ancestors() is inclusive: it first yields `current_directory`
66 // as-is.
67 // as-is.
67 for ancestor in current_directory.ancestors() {
68 for ancestor in current_directory.ancestors() {
68 if is_dir(ancestor.join(".hg"))? {
69 if is_dir(ancestor.join(".hg"))? {
69 return Ok(ancestor.to_path_buf());
70 return Ok(ancestor.to_path_buf());
70 }
71 }
71 }
72 }
72 return Err(RepoError::NotFound {
73 return Err(RepoError::NotFound {
73 at: current_directory,
74 at: current_directory,
74 });
75 });
75 }
76 }
76
77
77 /// Find a repository, either at the given path (which must contain a `.hg`
78 /// Find a repository, either at the given path (which must contain a `.hg`
78 /// sub-directory) or by searching the current directory and its
79 /// sub-directory) or by searching the current directory and its
79 /// ancestors.
80 /// ancestors.
80 ///
81 ///
81 /// A method with two very different "modes" like this usually a code smell
82 /// A method with two very different "modes" like this usually a code smell
82 /// to make two methods instead, but in this case an `Option` is what rhg
83 /// to make two methods instead, but in this case an `Option` is what rhg
83 /// sub-commands get from Clap for the `-R` / `--repository` CLI argument.
84 /// sub-commands get from Clap for the `-R` / `--repository` CLI argument.
84 /// Having two methods would just move that `if` to almost all callers.
85 /// Having two methods would just move that `if` to almost all callers.
85 pub fn find(
86 pub fn find(
86 config: &Config,
87 config: &Config,
87 explicit_path: Option<PathBuf>,
88 explicit_path: Option<PathBuf>,
88 ) -> Result<Self, RepoError> {
89 ) -> Result<Self, RepoError> {
89 if let Some(root) = explicit_path {
90 if let Some(root) = explicit_path {
90 if is_dir(root.join(".hg"))? {
91 if is_dir(root.join(".hg"))? {
91 Self::new_at_path(root.to_owned(), config)
92 Self::new_at_path(root.to_owned(), config)
92 } else if is_file(&root)? {
93 } else if is_file(&root)? {
93 Err(HgError::unsupported("bundle repository").into())
94 Err(HgError::unsupported("bundle repository").into())
94 } else {
95 } else {
95 Err(RepoError::NotFound {
96 Err(RepoError::NotFound {
96 at: root.to_owned(),
97 at: root.to_owned(),
97 })
98 })
98 }
99 }
99 } else {
100 } else {
100 let root = Self::find_repo_root()?;
101 let root = Self::find_repo_root()?;
101 Self::new_at_path(root, config)
102 Self::new_at_path(root, config)
102 }
103 }
103 }
104 }
104
105
105 /// To be called after checking that `.hg` is a sub-directory
106 /// To be called after checking that `.hg` is a sub-directory
106 fn new_at_path(
107 fn new_at_path(
107 working_directory: PathBuf,
108 working_directory: PathBuf,
108 config: &Config,
109 config: &Config,
109 ) -> Result<Self, RepoError> {
110 ) -> Result<Self, RepoError> {
110 let dot_hg = working_directory.join(".hg");
111 let dot_hg = working_directory.join(".hg");
111
112
112 let mut repo_config_files = Vec::new();
113 let mut repo_config_files = Vec::new();
113 repo_config_files.push(dot_hg.join("hgrc"));
114 repo_config_files.push(dot_hg.join("hgrc"));
114 repo_config_files.push(dot_hg.join("hgrc-not-shared"));
115 repo_config_files.push(dot_hg.join("hgrc-not-shared"));
115
116
116 let hg_vfs = Vfs { base: &dot_hg };
117 let hg_vfs = Vfs { base: &dot_hg };
117 let mut reqs = requirements::load_if_exists(hg_vfs)?;
118 let mut reqs = requirements::load_if_exists(hg_vfs)?;
118 let relative =
119 let relative =
119 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT);
120 reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT);
120 let shared =
121 let shared =
121 reqs.contains(requirements::SHARED_REQUIREMENT) || relative;
122 reqs.contains(requirements::SHARED_REQUIREMENT) || relative;
122
123
123 // From `mercurial/localrepo.py`:
124 // From `mercurial/localrepo.py`:
124 //
125 //
125 // if .hg/requires contains the sharesafe requirement, it means
126 // if .hg/requires contains the sharesafe requirement, it means
126 // there exists a `.hg/store/requires` too and we should read it
127 // there exists a `.hg/store/requires` too and we should read it
127 // NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
128 // NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
128 // is present. We never write SHARESAFE_REQUIREMENT for a repo if store
129 // is present. We never write SHARESAFE_REQUIREMENT for a repo if store
129 // is not present, refer checkrequirementscompat() for that
130 // is not present, refer checkrequirementscompat() for that
130 //
131 //
131 // However, if SHARESAFE_REQUIREMENT is not present, it means that the
132 // However, if SHARESAFE_REQUIREMENT is not present, it means that the
132 // repository was shared the old way. We check the share source
133 // repository was shared the old way. We check the share source
133 // .hg/requires for SHARESAFE_REQUIREMENT to detect whether the
134 // .hg/requires for SHARESAFE_REQUIREMENT to detect whether the
134 // current repository needs to be reshared
135 // current repository needs to be reshared
135 let share_safe = reqs.contains(requirements::SHARESAFE_REQUIREMENT);
136 let share_safe = reqs.contains(requirements::SHARESAFE_REQUIREMENT);
136
137
137 let store_path;
138 let store_path;
138 if !shared {
139 if !shared {
139 store_path = dot_hg.join("store");
140 store_path = dot_hg.join("store");
140 } else {
141 } else {
141 let bytes = hg_vfs.read("sharedpath")?;
142 let bytes = hg_vfs.read("sharedpath")?;
142 let mut shared_path =
143 let mut shared_path =
143 get_path_from_bytes(bytes.trim_end_matches(|b| b == b'\n'))
144 get_path_from_bytes(bytes.trim_end_matches(|b| b == b'\n'))
144 .to_owned();
145 .to_owned();
145 if relative {
146 if relative {
146 shared_path = dot_hg.join(shared_path)
147 shared_path = dot_hg.join(shared_path)
147 }
148 }
148 if !is_dir(&shared_path)? {
149 if !is_dir(&shared_path)? {
149 return Err(HgError::corrupted(format!(
150 return Err(HgError::corrupted(format!(
150 ".hg/sharedpath points to nonexistent directory {}",
151 ".hg/sharedpath points to nonexistent directory {}",
151 shared_path.display()
152 shared_path.display()
152 ))
153 ))
153 .into());
154 .into());
154 }
155 }
155
156
156 store_path = shared_path.join("store");
157 store_path = shared_path.join("store");
157
158
158 let source_is_share_safe =
159 let source_is_share_safe =
159 requirements::load(Vfs { base: &shared_path })?
160 requirements::load(Vfs { base: &shared_path })?
160 .contains(requirements::SHARESAFE_REQUIREMENT);
161 .contains(requirements::SHARESAFE_REQUIREMENT);
161
162
162 if share_safe != source_is_share_safe {
163 if share_safe != source_is_share_safe {
163 return Err(HgError::unsupported("share-safe mismatch").into());
164 return Err(HgError::unsupported("share-safe mismatch").into());
164 }
165 }
165
166
166 if share_safe {
167 if share_safe {
167 repo_config_files.insert(0, shared_path.join("hgrc"))
168 repo_config_files.insert(0, shared_path.join("hgrc"))
168 }
169 }
169 }
170 }
170 if share_safe {
171 if share_safe {
171 reqs.extend(requirements::load(Vfs { base: &store_path })?);
172 reqs.extend(requirements::load(Vfs { base: &store_path })?);
172 }
173 }
173
174
174 let repo_config = if std::env::var_os("HGRCSKIPREPO").is_none() {
175 let repo_config = if std::env::var_os("HGRCSKIPREPO").is_none() {
175 config.combine_with_repo(&repo_config_files)?
176 config.combine_with_repo(&repo_config_files)?
176 } else {
177 } else {
177 config.clone()
178 config.clone()
178 };
179 };
179
180
180 let repo = Self {
181 let repo = Self {
181 requirements: reqs,
182 requirements: reqs,
182 working_directory,
183 working_directory,
183 store: store_path,
184 store: store_path,
184 dot_hg,
185 dot_hg,
185 config: repo_config,
186 config: repo_config,
186 dirstate_parents: LazyCell::new(),
187 dirstate_parents: LazyCell::new(),
187 dirstate_data_file_uuid: LazyCell::new(),
188 dirstate_data_file_uuid: LazyCell::new(),
188 dirstate_map: LazyCell::new(),
189 dirstate_map: LazyCell::new(),
189 changelog: LazyCell::new(),
190 changelog: LazyCell::new(),
190 manifestlog: LazyCell::new(),
191 manifestlog: LazyCell::new(),
191 };
192 };
192
193
193 requirements::check(&repo)?;
194 requirements::check(&repo)?;
194
195
195 Ok(repo)
196 Ok(repo)
196 }
197 }
197
198
198 pub fn working_directory_path(&self) -> &Path {
199 pub fn working_directory_path(&self) -> &Path {
199 &self.working_directory
200 &self.working_directory
200 }
201 }
201
202
202 pub fn requirements(&self) -> &HashSet<String> {
203 pub fn requirements(&self) -> &HashSet<String> {
203 &self.requirements
204 &self.requirements
204 }
205 }
205
206
206 pub fn config(&self) -> &Config {
207 pub fn config(&self) -> &Config {
207 &self.config
208 &self.config
208 }
209 }
209
210
210 /// For accessing repository files (in `.hg`), except for the store
211 /// For accessing repository files (in `.hg`), except for the store
211 /// (`.hg/store`).
212 /// (`.hg/store`).
212 pub fn hg_vfs(&self) -> Vfs<'_> {
213 pub fn hg_vfs(&self) -> Vfs<'_> {
213 Vfs { base: &self.dot_hg }
214 Vfs { base: &self.dot_hg }
214 }
215 }
215
216
216 /// For accessing repository store files (in `.hg/store`)
217 /// For accessing repository store files (in `.hg/store`)
217 pub fn store_vfs(&self) -> Vfs<'_> {
218 pub fn store_vfs(&self) -> Vfs<'_> {
218 Vfs { base: &self.store }
219 Vfs { base: &self.store }
219 }
220 }
220
221
221 /// For accessing the working copy
222 /// For accessing the working copy
222 pub fn working_directory_vfs(&self) -> Vfs<'_> {
223 pub fn working_directory_vfs(&self) -> Vfs<'_> {
223 Vfs {
224 Vfs {
224 base: &self.working_directory,
225 base: &self.working_directory,
225 }
226 }
226 }
227 }
227
228
228 pub fn try_with_wlock_no_wait<R>(
229 pub fn try_with_wlock_no_wait<R>(
229 &self,
230 &self,
230 f: impl FnOnce() -> R,
231 f: impl FnOnce() -> R,
231 ) -> Result<R, LockError> {
232 ) -> Result<R, LockError> {
232 try_with_lock_no_wait(self.hg_vfs(), "wlock", f)
233 try_with_lock_no_wait(self.hg_vfs(), "wlock", f)
233 }
234 }
234
235
235 pub fn has_dirstate_v2(&self) -> bool {
236 pub fn has_dirstate_v2(&self) -> bool {
236 self.requirements
237 self.requirements
237 .contains(requirements::DIRSTATE_V2_REQUIREMENT)
238 .contains(requirements::DIRSTATE_V2_REQUIREMENT)
238 }
239 }
239
240
240 pub fn has_sparse(&self) -> bool {
241 pub fn has_sparse(&self) -> bool {
241 self.requirements.contains(requirements::SPARSE_REQUIREMENT)
242 self.requirements.contains(requirements::SPARSE_REQUIREMENT)
242 }
243 }
243
244
244 pub fn has_narrow(&self) -> bool {
245 pub fn has_narrow(&self) -> bool {
245 self.requirements.contains(requirements::NARROW_REQUIREMENT)
246 self.requirements.contains(requirements::NARROW_REQUIREMENT)
246 }
247 }
247
248
248 pub fn has_nodemap(&self) -> bool {
249 pub fn has_nodemap(&self) -> bool {
249 self.requirements
250 self.requirements
250 .contains(requirements::NODEMAP_REQUIREMENT)
251 .contains(requirements::NODEMAP_REQUIREMENT)
251 }
252 }
252
253
253 fn dirstate_file_contents(&self) -> Result<Vec<u8>, HgError> {
254 fn dirstate_file_contents(&self) -> Result<Vec<u8>, HgError> {
254 Ok(self
255 Ok(self
255 .hg_vfs()
256 .hg_vfs()
256 .read("dirstate")
257 .read("dirstate")
257 .io_not_found_as_none()?
258 .io_not_found_as_none()?
258 .unwrap_or(Vec::new()))
259 .unwrap_or(Vec::new()))
259 }
260 }
260
261
261 pub fn dirstate_parents(&self) -> Result<DirstateParents, HgError> {
262 pub fn dirstate_parents(&self) -> Result<DirstateParents, HgError> {
262 Ok(*self
263 Ok(*self
263 .dirstate_parents
264 .dirstate_parents
264 .get_or_init(|| self.read_dirstate_parents())?)
265 .get_or_init(|| self.read_dirstate_parents())?)
265 }
266 }
266
267
267 fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> {
268 fn read_dirstate_parents(&self) -> Result<DirstateParents, HgError> {
268 let dirstate = self.dirstate_file_contents()?;
269 let dirstate = self.dirstate_file_contents()?;
269 let parents = if dirstate.is_empty() {
270 let parents = if dirstate.is_empty() {
270 if self.has_dirstate_v2() {
271 if self.has_dirstate_v2() {
271 self.dirstate_data_file_uuid.set(None);
272 self.dirstate_data_file_uuid.set(None);
272 }
273 }
273 DirstateParents::NULL
274 DirstateParents::NULL
274 } else if self.has_dirstate_v2() {
275 } else if self.has_dirstate_v2() {
275 let docket =
276 let docket =
276 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
277 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
277 self.dirstate_data_file_uuid
278 self.dirstate_data_file_uuid
278 .set(Some(docket.uuid.to_owned()));
279 .set(Some(docket.uuid.to_owned()));
279 docket.parents()
280 docket.parents()
280 } else {
281 } else {
281 crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?
282 crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?
282 .clone()
283 .clone()
283 };
284 };
284 self.dirstate_parents.set(parents);
285 self.dirstate_parents.set(parents);
285 Ok(parents)
286 Ok(parents)
286 }
287 }
287
288
288 fn read_dirstate_data_file_uuid(
289 fn read_dirstate_data_file_uuid(
289 &self,
290 &self,
290 ) -> Result<Option<Vec<u8>>, HgError> {
291 ) -> Result<Option<Vec<u8>>, HgError> {
291 assert!(
292 assert!(
292 self.has_dirstate_v2(),
293 self.has_dirstate_v2(),
293 "accessing dirstate data file ID without dirstate-v2"
294 "accessing dirstate data file ID without dirstate-v2"
294 );
295 );
295 let dirstate = self.dirstate_file_contents()?;
296 let dirstate = self.dirstate_file_contents()?;
296 if dirstate.is_empty() {
297 if dirstate.is_empty() {
297 self.dirstate_parents.set(DirstateParents::NULL);
298 self.dirstate_parents.set(DirstateParents::NULL);
298 Ok(None)
299 Ok(None)
299 } else {
300 } else {
300 let docket =
301 let docket =
301 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
302 crate::dirstate_tree::on_disk::read_docket(&dirstate)?;
302 self.dirstate_parents.set(docket.parents());
303 self.dirstate_parents.set(docket.parents());
303 Ok(Some(docket.uuid.to_owned()))
304 Ok(Some(docket.uuid.to_owned()))
304 }
305 }
305 }
306 }
306
307
307 fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> {
308 fn new_dirstate_map(&self) -> Result<OwningDirstateMap, DirstateError> {
308 if self.has_dirstate_v2() {
309 if self.has_dirstate_v2() {
309 self.read_docket_and_data_file()
310 self.read_docket_and_data_file()
310 } else {
311 } else {
312 debug_wait_for_file_or_print(
313 self.config(),
314 "dirstate.pre-read-file",
315 );
311 let dirstate_file_contents = self.dirstate_file_contents()?;
316 let dirstate_file_contents = self.dirstate_file_contents()?;
312 if dirstate_file_contents.is_empty() {
317 if dirstate_file_contents.is_empty() {
313 self.dirstate_parents.set(DirstateParents::NULL);
318 self.dirstate_parents.set(DirstateParents::NULL);
314 Ok(OwningDirstateMap::new_empty(Vec::new()))
319 Ok(OwningDirstateMap::new_empty(Vec::new()))
315 } else {
320 } else {
316 let (map, parents) =
321 let (map, parents) =
317 OwningDirstateMap::new_v1(dirstate_file_contents)?;
322 OwningDirstateMap::new_v1(dirstate_file_contents)?;
318 self.dirstate_parents.set(parents);
323 self.dirstate_parents.set(parents);
319 Ok(map)
324 Ok(map)
320 }
325 }
321 }
326 }
322 }
327 }
323
328
324 fn read_docket_and_data_file(
329 fn read_docket_and_data_file(
325 &self,
330 &self,
326 ) -> Result<OwningDirstateMap, DirstateError> {
331 ) -> Result<OwningDirstateMap, DirstateError> {
332 debug_wait_for_file_or_print(self.config(), "dirstate.pre-read-file");
327 let dirstate_file_contents = self.dirstate_file_contents()?;
333 let dirstate_file_contents = self.dirstate_file_contents()?;
328 if dirstate_file_contents.is_empty() {
334 if dirstate_file_contents.is_empty() {
329 self.dirstate_parents.set(DirstateParents::NULL);
335 self.dirstate_parents.set(DirstateParents::NULL);
330 self.dirstate_data_file_uuid.set(None);
336 self.dirstate_data_file_uuid.set(None);
331 return Ok(OwningDirstateMap::new_empty(Vec::new()));
337 return Ok(OwningDirstateMap::new_empty(Vec::new()));
332 }
338 }
333 let docket = crate::dirstate_tree::on_disk::read_docket(
339 let docket = crate::dirstate_tree::on_disk::read_docket(
334 &dirstate_file_contents,
340 &dirstate_file_contents,
335 )?;
341 )?;
336 self.dirstate_parents.set(docket.parents());
342 self.dirstate_parents.set(docket.parents());
337 self.dirstate_data_file_uuid
343 self.dirstate_data_file_uuid
338 .set(Some(docket.uuid.to_owned()));
344 .set(Some(docket.uuid.to_owned()));
339 let data_size = docket.data_size();
345 let data_size = docket.data_size();
340 let metadata = docket.tree_metadata();
346 let metadata = docket.tree_metadata();
341 let mut map = if crate::vfs::is_on_nfs_mount(docket.data_filename()) {
347 let mut map = if crate::vfs::is_on_nfs_mount(docket.data_filename()) {
342 // Don't mmap on NFS to prevent `SIGBUS` error on deletion
348 // Don't mmap on NFS to prevent `SIGBUS` error on deletion
343 OwningDirstateMap::new_v2(
349 OwningDirstateMap::new_v2(
344 self.hg_vfs().read(docket.data_filename())?,
350 self.hg_vfs().read(docket.data_filename())?,
345 data_size,
351 data_size,
346 metadata,
352 metadata,
347 )
353 )
348 } else if let Some(data_mmap) = self
354 } else if let Some(data_mmap) = self
349 .hg_vfs()
355 .hg_vfs()
350 .mmap_open(docket.data_filename())
356 .mmap_open(docket.data_filename())
351 .io_not_found_as_none()?
357 .io_not_found_as_none()?
352 {
358 {
353 OwningDirstateMap::new_v2(data_mmap, data_size, metadata)
359 OwningDirstateMap::new_v2(data_mmap, data_size, metadata)
354 } else {
360 } else {
355 OwningDirstateMap::new_v2(Vec::new(), data_size, metadata)
361 OwningDirstateMap::new_v2(Vec::new(), data_size, metadata)
356 }?;
362 }?;
357
363
358 let write_mode_config = self
364 let write_mode_config = self
359 .config()
365 .config()
360 .get_str(b"devel", b"dirstate.v2.data_update_mode")
366 .get_str(b"devel", b"dirstate.v2.data_update_mode")
361 .unwrap_or(Some("auto"))
367 .unwrap_or(Some("auto"))
362 .unwrap_or("auto"); // don't bother for devel options
368 .unwrap_or("auto"); // don't bother for devel options
363 let write_mode = match write_mode_config {
369 let write_mode = match write_mode_config {
364 "auto" => DirstateMapWriteMode::Auto,
370 "auto" => DirstateMapWriteMode::Auto,
365 "force-new" => DirstateMapWriteMode::ForceNewDataFile,
371 "force-new" => DirstateMapWriteMode::ForceNewDataFile,
366 "force-append" => DirstateMapWriteMode::ForceAppend,
372 "force-append" => DirstateMapWriteMode::ForceAppend,
367 _ => DirstateMapWriteMode::Auto,
373 _ => DirstateMapWriteMode::Auto,
368 };
374 };
369
375
370 map.with_dmap_mut(|m| m.set_write_mode(write_mode));
376 map.with_dmap_mut(|m| m.set_write_mode(write_mode));
371
377
372 Ok(map)
378 Ok(map)
373 }
379 }
374
380
375 pub fn dirstate_map(
381 pub fn dirstate_map(
376 &self,
382 &self,
377 ) -> Result<Ref<OwningDirstateMap>, DirstateError> {
383 ) -> Result<Ref<OwningDirstateMap>, DirstateError> {
378 self.dirstate_map.get_or_init(|| self.new_dirstate_map())
384 self.dirstate_map.get_or_init(|| self.new_dirstate_map())
379 }
385 }
380
386
381 pub fn dirstate_map_mut(
387 pub fn dirstate_map_mut(
382 &self,
388 &self,
383 ) -> Result<RefMut<OwningDirstateMap>, DirstateError> {
389 ) -> Result<RefMut<OwningDirstateMap>, DirstateError> {
384 self.dirstate_map
390 self.dirstate_map
385 .get_mut_or_init(|| self.new_dirstate_map())
391 .get_mut_or_init(|| self.new_dirstate_map())
386 }
392 }
387
393
388 fn new_changelog(&self) -> Result<Changelog, HgError> {
394 fn new_changelog(&self) -> Result<Changelog, HgError> {
389 Changelog::open(&self.store_vfs(), self.has_nodemap())
395 Changelog::open(&self.store_vfs(), self.has_nodemap())
390 }
396 }
391
397
392 pub fn changelog(&self) -> Result<Ref<Changelog>, HgError> {
398 pub fn changelog(&self) -> Result<Ref<Changelog>, HgError> {
393 self.changelog.get_or_init(|| self.new_changelog())
399 self.changelog.get_or_init(|| self.new_changelog())
394 }
400 }
395
401
396 pub fn changelog_mut(&self) -> Result<RefMut<Changelog>, HgError> {
402 pub fn changelog_mut(&self) -> Result<RefMut<Changelog>, HgError> {
397 self.changelog.get_mut_or_init(|| self.new_changelog())
403 self.changelog.get_mut_or_init(|| self.new_changelog())
398 }
404 }
399
405
400 fn new_manifestlog(&self) -> Result<Manifestlog, HgError> {
406 fn new_manifestlog(&self) -> Result<Manifestlog, HgError> {
401 Manifestlog::open(&self.store_vfs(), self.has_nodemap())
407 Manifestlog::open(&self.store_vfs(), self.has_nodemap())
402 }
408 }
403
409
404 pub fn manifestlog(&self) -> Result<Ref<Manifestlog>, HgError> {
410 pub fn manifestlog(&self) -> Result<Ref<Manifestlog>, HgError> {
405 self.manifestlog.get_or_init(|| self.new_manifestlog())
411 self.manifestlog.get_or_init(|| self.new_manifestlog())
406 }
412 }
407
413
408 pub fn manifestlog_mut(&self) -> Result<RefMut<Manifestlog>, HgError> {
414 pub fn manifestlog_mut(&self) -> Result<RefMut<Manifestlog>, HgError> {
409 self.manifestlog.get_mut_or_init(|| self.new_manifestlog())
415 self.manifestlog.get_mut_or_init(|| self.new_manifestlog())
410 }
416 }
411
417
412 /// Returns the manifest of the *changeset* with the given node ID
418 /// Returns the manifest of the *changeset* with the given node ID
413 pub fn manifest_for_node(
419 pub fn manifest_for_node(
414 &self,
420 &self,
415 node: impl Into<NodePrefix>,
421 node: impl Into<NodePrefix>,
416 ) -> Result<Manifest, RevlogError> {
422 ) -> Result<Manifest, RevlogError> {
417 self.manifestlog()?.data_for_node(
423 self.manifestlog()?.data_for_node(
418 self.changelog()?
424 self.changelog()?
419 .data_for_node(node.into())?
425 .data_for_node(node.into())?
420 .manifest_node()?
426 .manifest_node()?
421 .into(),
427 .into(),
422 )
428 )
423 }
429 }
424
430
425 /// Returns the manifest of the *changeset* with the given revision number
431 /// Returns the manifest of the *changeset* with the given revision number
426 pub fn manifest_for_rev(
432 pub fn manifest_for_rev(
427 &self,
433 &self,
428 revision: Revision,
434 revision: Revision,
429 ) -> Result<Manifest, RevlogError> {
435 ) -> Result<Manifest, RevlogError> {
430 self.manifestlog()?.data_for_node(
436 self.manifestlog()?.data_for_node(
431 self.changelog()?
437 self.changelog()?
432 .data_for_rev(revision)?
438 .data_for_rev(revision)?
433 .manifest_node()?
439 .manifest_node()?
434 .into(),
440 .into(),
435 )
441 )
436 }
442 }
437
443
438 pub fn has_subrepos(&self) -> Result<bool, DirstateError> {
444 pub fn has_subrepos(&self) -> Result<bool, DirstateError> {
439 if let Some(entry) = self.dirstate_map()?.get(HgPath::new(".hgsub"))? {
445 if let Some(entry) = self.dirstate_map()?.get(HgPath::new(".hgsub"))? {
440 Ok(entry.tracked())
446 Ok(entry.tracked())
441 } else {
447 } else {
442 Ok(false)
448 Ok(false)
443 }
449 }
444 }
450 }
445
451
446 pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> {
452 pub fn filelog(&self, path: &HgPath) -> Result<Filelog, HgError> {
447 Filelog::open(self, path)
453 Filelog::open(self, path)
448 }
454 }
449
455
450 /// Write to disk any updates that were made through `dirstate_map_mut`.
456 /// Write to disk any updates that were made through `dirstate_map_mut`.
451 ///
457 ///
452 /// The "wlock" must be held while calling this.
458 /// The "wlock" must be held while calling this.
453 /// See for example `try_with_wlock_no_wait`.
459 /// See for example `try_with_wlock_no_wait`.
454 ///
460 ///
455 /// TODO: have a `WritableRepo` type only accessible while holding the
461 /// TODO: have a `WritableRepo` type only accessible while holding the
456 /// lock?
462 /// lock?
457 pub fn write_dirstate(&self) -> Result<(), DirstateError> {
463 pub fn write_dirstate(&self) -> Result<(), DirstateError> {
458 let map = self.dirstate_map()?;
464 let map = self.dirstate_map()?;
459 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if
465 // TODO: Maintain a `DirstateMap::dirty` flag, and return early here if
460 // it’s unset
466 // it’s unset
461 let parents = self.dirstate_parents()?;
467 let parents = self.dirstate_parents()?;
462 let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() {
468 let (packed_dirstate, old_uuid_to_remove) = if self.has_dirstate_v2() {
463 let uuid_opt = self
469 let uuid_opt = self
464 .dirstate_data_file_uuid
470 .dirstate_data_file_uuid
465 .get_or_init(|| self.read_dirstate_data_file_uuid())?;
471 .get_or_init(|| self.read_dirstate_data_file_uuid())?;
466 let uuid_opt = uuid_opt.as_ref();
472 let uuid_opt = uuid_opt.as_ref();
467 let write_mode = if uuid_opt.is_some() {
473 let write_mode = if uuid_opt.is_some() {
468 DirstateMapWriteMode::Auto
474 DirstateMapWriteMode::Auto
469 } else {
475 } else {
470 DirstateMapWriteMode::ForceNewDataFile
476 DirstateMapWriteMode::ForceNewDataFile
471 };
477 };
472 let (data, tree_metadata, append, old_data_size) =
478 let (data, tree_metadata, append, old_data_size) =
473 map.pack_v2(write_mode)?;
479 map.pack_v2(write_mode)?;
474
480
475 // Reuse the uuid, or generate a new one, keeping the old for
481 // Reuse the uuid, or generate a new one, keeping the old for
476 // deletion.
482 // deletion.
477 let (uuid, old_uuid) = match uuid_opt {
483 let (uuid, old_uuid) = match uuid_opt {
478 Some(uuid) => {
484 Some(uuid) => {
479 let as_str = std::str::from_utf8(uuid)
485 let as_str = std::str::from_utf8(uuid)
480 .map_err(|_| {
486 .map_err(|_| {
481 HgError::corrupted(
487 HgError::corrupted(
482 "non-UTF-8 dirstate data file ID",
488 "non-UTF-8 dirstate data file ID",
483 )
489 )
484 })?
490 })?
485 .to_owned();
491 .to_owned();
486 if append {
492 if append {
487 (as_str, None)
493 (as_str, None)
488 } else {
494 } else {
489 (DirstateDocket::new_uid(), Some(as_str))
495 (DirstateDocket::new_uid(), Some(as_str))
490 }
496 }
491 }
497 }
492 None => (DirstateDocket::new_uid(), None),
498 None => (DirstateDocket::new_uid(), None),
493 };
499 };
494
500
495 let data_filename = format!("dirstate.{}", uuid);
501 let data_filename = format!("dirstate.{}", uuid);
496 let data_filename = self.hg_vfs().join(data_filename);
502 let data_filename = self.hg_vfs().join(data_filename);
497 let mut options = std::fs::OpenOptions::new();
503 let mut options = std::fs::OpenOptions::new();
498 options.write(true);
504 options.write(true);
499
505
500 // Why are we not using the O_APPEND flag when appending?
506 // Why are we not using the O_APPEND flag when appending?
501 //
507 //
502 // - O_APPEND makes it trickier to deal with garbage at the end of
508 // - O_APPEND makes it trickier to deal with garbage at the end of
503 // the file, left by a previous uncommitted transaction. By
509 // the file, left by a previous uncommitted transaction. By
504 // starting the write at [old_data_size] we make sure we erase
510 // starting the write at [old_data_size] we make sure we erase
505 // all such garbage.
511 // all such garbage.
506 //
512 //
507 // - O_APPEND requires to special-case 0-byte writes, whereas we
513 // - O_APPEND requires to special-case 0-byte writes, whereas we
508 // don't need that.
514 // don't need that.
509 //
515 //
510 // - Some OSes have bugs in implementation O_APPEND:
516 // - Some OSes have bugs in implementation O_APPEND:
511 // revlog.py talks about a Solaris bug, but we also saw some ZFS
517 // revlog.py talks about a Solaris bug, but we also saw some ZFS
512 // bug: https://github.com/openzfs/zfs/pull/3124,
518 // bug: https://github.com/openzfs/zfs/pull/3124,
513 // https://github.com/openzfs/zfs/issues/13370
519 // https://github.com/openzfs/zfs/issues/13370
514 //
520 //
515 if !append {
521 if !append {
516 log::trace!("creating a new dirstate data file");
522 log::trace!("creating a new dirstate data file");
517 options.create_new(true);
523 options.create_new(true);
518 } else {
524 } else {
519 log::trace!("appending to the dirstate data file");
525 log::trace!("appending to the dirstate data file");
520 }
526 }
521
527
522 let data_size = (|| {
528 let data_size = (|| {
523 // TODO: loop and try another random ID if !append and this
529 // TODO: loop and try another random ID if !append and this
524 // returns `ErrorKind::AlreadyExists`? Collision chance of two
530 // returns `ErrorKind::AlreadyExists`? Collision chance of two
525 // random IDs is one in 2**32
531 // random IDs is one in 2**32
526 let mut file = options.open(&data_filename)?;
532 let mut file = options.open(&data_filename)?;
527 if append {
533 if append {
528 file.seek(SeekFrom::Start(old_data_size as u64))?;
534 file.seek(SeekFrom::Start(old_data_size as u64))?;
529 }
535 }
530 file.write_all(&data)?;
536 file.write_all(&data)?;
531 file.flush()?;
537 file.flush()?;
532 file.seek(SeekFrom::Current(0))
538 file.seek(SeekFrom::Current(0))
533 })()
539 })()
534 .when_writing_file(&data_filename)?;
540 .when_writing_file(&data_filename)?;
535
541
536 let packed_dirstate = DirstateDocket::serialize(
542 let packed_dirstate = DirstateDocket::serialize(
537 parents,
543 parents,
538 tree_metadata,
544 tree_metadata,
539 data_size,
545 data_size,
540 uuid.as_bytes(),
546 uuid.as_bytes(),
541 )
547 )
542 .map_err(|_: std::num::TryFromIntError| {
548 .map_err(|_: std::num::TryFromIntError| {
543 HgError::corrupted("overflow in dirstate docket serialization")
549 HgError::corrupted("overflow in dirstate docket serialization")
544 })?;
550 })?;
545
551
546 (packed_dirstate, old_uuid)
552 (packed_dirstate, old_uuid)
547 } else {
553 } else {
548 (map.pack_v1(parents)?, None)
554 (map.pack_v1(parents)?, None)
549 };
555 };
550
556
551 let vfs = self.hg_vfs();
557 let vfs = self.hg_vfs();
552 vfs.atomic_write("dirstate", &packed_dirstate)?;
558 vfs.atomic_write("dirstate", &packed_dirstate)?;
553 if let Some(uuid) = old_uuid_to_remove {
559 if let Some(uuid) = old_uuid_to_remove {
554 // Remove the old data file after the new docket pointing to the
560 // Remove the old data file after the new docket pointing to the
555 // new data file was written.
561 // new data file was written.
556 vfs.remove_file(format!("dirstate.{}", uuid))?;
562 vfs.remove_file(format!("dirstate.{}", uuid))?;
557 }
563 }
558 Ok(())
564 Ok(())
559 }
565 }
560 }
566 }
561
567
562 /// Lazily-initialized component of `Repo` with interior mutability
568 /// Lazily-initialized component of `Repo` with interior mutability
563 ///
569 ///
564 /// This differs from `OnceCell` in that the value can still be "deinitialized"
570 /// This differs from `OnceCell` in that the value can still be "deinitialized"
565 /// later by setting its inner `Option` to `None`. It also takes the
571 /// later by setting its inner `Option` to `None`. It also takes the
566 /// initialization function as an argument when the value is requested, not
572 /// initialization function as an argument when the value is requested, not
567 /// when the instance is created.
573 /// when the instance is created.
568 struct LazyCell<T> {
574 struct LazyCell<T> {
569 value: RefCell<Option<T>>,
575 value: RefCell<Option<T>>,
570 }
576 }
571
577
572 impl<T> LazyCell<T> {
578 impl<T> LazyCell<T> {
573 fn new() -> Self {
579 fn new() -> Self {
574 Self {
580 Self {
575 value: RefCell::new(None),
581 value: RefCell::new(None),
576 }
582 }
577 }
583 }
578
584
579 fn set(&self, value: T) {
585 fn set(&self, value: T) {
580 *self.value.borrow_mut() = Some(value)
586 *self.value.borrow_mut() = Some(value)
581 }
587 }
582
588
583 fn get_or_init<E>(
589 fn get_or_init<E>(
584 &self,
590 &self,
585 init: impl Fn() -> Result<T, E>,
591 init: impl Fn() -> Result<T, E>,
586 ) -> Result<Ref<T>, E> {
592 ) -> Result<Ref<T>, E> {
587 let mut borrowed = self.value.borrow();
593 let mut borrowed = self.value.borrow();
588 if borrowed.is_none() {
594 if borrowed.is_none() {
589 drop(borrowed);
595 drop(borrowed);
590 // Only use `borrow_mut` if it is really needed to avoid panic in
596 // Only use `borrow_mut` if it is really needed to avoid panic in
591 // case there is another outstanding borrow but mutation is not
597 // case there is another outstanding borrow but mutation is not
592 // needed.
598 // needed.
593 *self.value.borrow_mut() = Some(init()?);
599 *self.value.borrow_mut() = Some(init()?);
594 borrowed = self.value.borrow()
600 borrowed = self.value.borrow()
595 }
601 }
596 Ok(Ref::map(borrowed, |option| option.as_ref().unwrap()))
602 Ok(Ref::map(borrowed, |option| option.as_ref().unwrap()))
597 }
603 }
598
604
599 fn get_mut_or_init<E>(
605 fn get_mut_or_init<E>(
600 &self,
606 &self,
601 init: impl Fn() -> Result<T, E>,
607 init: impl Fn() -> Result<T, E>,
602 ) -> Result<RefMut<T>, E> {
608 ) -> Result<RefMut<T>, E> {
603 let mut borrowed = self.value.borrow_mut();
609 let mut borrowed = self.value.borrow_mut();
604 if borrowed.is_none() {
610 if borrowed.is_none() {
605 *borrowed = Some(init()?);
611 *borrowed = Some(init()?);
606 }
612 }
607 Ok(RefMut::map(borrowed, |option| option.as_mut().unwrap()))
613 Ok(RefMut::map(borrowed, |option| option.as_mut().unwrap()))
608 }
614 }
609 }
615 }
@@ -1,81 +1,87 b''
1 //! Utils for debugging hg-core
1 //! Utils for debugging hg-core
2
2
3 use crate::config::Config;
3 use crate::config::Config;
4
4
5 /// Write the file path given by the config option `devel.<config_option>` with
5 /// Write the file path given by the config option `devel.<config_option>` with
6 /// the suffix `.waiting`, then wait for the file path given by the
6 /// the suffix `.waiting`, then wait for the file path given by the
7 /// config option `devel.<config_option>` to appear on disk
7 /// config option `devel.<config_option>` to appear on disk
8 /// up to `devel.<config_option>-timeout` seconds.
8 /// up to `devel.<config_option>-timeout` seconds.
9 /// Note that the timeout may be higher because we scale it if global
9 /// Note that the timeout may be higher because we scale it if global
10 /// `run-tests` timeouts are raised to prevent flakiness on slower hardware.
10 /// `run-tests` timeouts are raised to prevent flakiness on slower hardware.
11 ///
11 ///
12 /// Useful for testing race conditions.
12 /// Useful for testing race conditions.
13 pub fn debug_wait_for_file(
13 pub fn debug_wait_for_file(
14 config: &Config,
14 config: &Config,
15 config_option: &str,
15 config_option: &str,
16 ) -> Result<(), String> {
16 ) -> Result<(), String> {
17 let path_opt = format!("sync.{config_option}");
17 let path_opt = format!("sync.{config_option}");
18 let file_path = match config.get_str(b"devel", path_opt.as_bytes()).ok() {
18 let file_path = match config.get_str(b"devel", path_opt.as_bytes()).ok() {
19 Some(Some(file_path)) => file_path,
19 Some(Some(file_path)) => file_path,
20 _ => return Ok(()),
20 _ => return Ok(()),
21 };
21 };
22
22
23 // TODO make it so `configitems` is shared between Rust and Python so that
23 // TODO make it so `configitems` is shared between Rust and Python so that
24 // defaults work out of the box, etc.
24 // defaults work out of the box, etc.
25 let default_timeout = 2;
25 let default_timeout = 2;
26 let timeout_opt = format!("sync.{config_option}-timeout");
26 let timeout_opt = format!("sync.{config_option}-timeout");
27 let timeout_seconds =
27 let timeout_seconds =
28 match config.get_u32(b"devel", timeout_opt.as_bytes()) {
28 match config.get_u32(b"devel", timeout_opt.as_bytes()) {
29 Ok(Some(timeout)) => timeout,
29 Ok(Some(timeout)) => timeout,
30 Err(e) => {
30 Err(e) => {
31 log::debug!("{e}");
31 log::debug!("{e}");
32 default_timeout
32 default_timeout
33 }
33 }
34 _ => default_timeout,
34 _ => default_timeout,
35 };
35 };
36 let timeout_seconds = timeout_seconds as u64;
36 let timeout_seconds = timeout_seconds as u64;
37
37
38 log::debug!(
38 log::debug!(
39 "Config option `{config_option}` found, \
39 "Config option `{config_option}` found, \
40 waiting for file `{file_path}` to be created"
40 waiting for file `{file_path}` to be created"
41 );
41 );
42 std::fs::File::create(format!("{file_path}.waiting")).ok();
42 std::fs::File::create(format!("{file_path}.waiting")).ok();
43 // If the test timeout have been extended, scale the timer relative
43 // If the test timeout have been extended, scale the timer relative
44 // to the normal timing.
44 // to the normal timing.
45 let global_default_timeout: u64 = std::env::var("HGTEST_TIMEOUT_DEFAULT")
45 let global_default_timeout: u64 = std::env::var("HGTEST_TIMEOUT_DEFAULT")
46 .map(|t| t.parse())
46 .map(|t| t.parse())
47 .unwrap_or(Ok(0))
47 .unwrap_or(Ok(0))
48 .unwrap();
48 .unwrap();
49 let global_timeout_override: u64 = std::env::var("HGTEST_TIMEOUT")
49 let global_timeout_override: u64 = std::env::var("HGTEST_TIMEOUT")
50 .map(|t| t.parse())
50 .map(|t| t.parse())
51 .unwrap_or(Ok(0))
51 .unwrap_or(Ok(0))
52 .unwrap();
52 .unwrap();
53 let timeout_seconds = if global_default_timeout < global_timeout_override {
53 let timeout_seconds = if global_default_timeout < global_timeout_override {
54 timeout_seconds * global_timeout_override / global_default_timeout
54 timeout_seconds * global_timeout_override / global_default_timeout
55 } else {
55 } else {
56 timeout_seconds
56 timeout_seconds
57 };
57 };
58 let timeout = std::time::Duration::from_secs(timeout_seconds);
58 let timeout = std::time::Duration::from_secs(timeout_seconds);
59
59
60 let start = std::time::Instant::now();
60 let start = std::time::Instant::now();
61 let path = std::path::Path::new(file_path);
61 let path = std::path::Path::new(file_path);
62 let mut found = false;
62 let mut found = false;
63 while start.elapsed() < timeout {
63 while start.elapsed() < timeout {
64 if path.exists() {
64 if path.exists() {
65 log::debug!("File `{file_path}` was created");
65 log::debug!("File `{file_path}` was created");
66 found = true;
66 found = true;
67 break;
67 break;
68 } else {
68 } else {
69 std::thread::sleep(std::time::Duration::from_millis(10));
69 std::thread::sleep(std::time::Duration::from_millis(10));
70 }
70 }
71 }
71 }
72 if !found {
72 if !found {
73 let msg = format!(
73 let msg = format!(
74 "File `{file_path}` set by `{config_option}` was not found \
74 "File `{file_path}` set by `{config_option}` was not found \
75 within the allocated {timeout_seconds} seconds timeout"
75 within the allocated {timeout_seconds} seconds timeout"
76 );
76 );
77 Err(msg)
77 Err(msg)
78 } else {
78 } else {
79 Ok(())
79 Ok(())
80 }
80 }
81 }
81 }
82
83 pub fn debug_wait_for_file_or_print(config: &Config, config_option: &str) {
84 if let Err(e) = debug_wait_for_file(&config, config_option) {
85 eprintln!("{e}");
86 };
87 }
General Comments 0
You need to be logged in to leave comments. Login now