##// END OF EJS Templates
nodemap: automatically "vacuum" the persistent nodemap when too sparse...
marmoute -
r45126:c70bcaf7 default
parent child Browse files
Show More
@@ -1,1580 +1,1579
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import functools
11 11 import re
12 12
13 13 from . import (
14 14 encoding,
15 15 error,
16 16 )
17 17
18 18
19 19 def loadconfigtable(ui, extname, configtable):
20 20 """update config item known to the ui with the extension ones"""
21 21 for section, items in sorted(configtable.items()):
22 22 knownitems = ui._knownconfig.setdefault(section, itemregister())
23 23 knownkeys = set(knownitems)
24 24 newkeys = set(items)
25 25 for key in sorted(knownkeys & newkeys):
26 26 msg = b"extension '%s' overwrite config item '%s.%s'"
27 27 msg %= (extname, section, key)
28 28 ui.develwarn(msg, config=b'warn-config')
29 29
30 30 knownitems.update(items)
31 31
32 32
33 33 class configitem(object):
34 34 """represent a known config item
35 35
36 36 :section: the official config section where to find this item,
37 37 :name: the official name within the section,
38 38 :default: default value for this item,
39 39 :alias: optional list of tuples as alternatives,
40 40 :generic: this is a generic definition, match name using regular expression.
41 41 """
42 42
43 43 def __init__(
44 44 self,
45 45 section,
46 46 name,
47 47 default=None,
48 48 alias=(),
49 49 generic=False,
50 50 priority=0,
51 51 experimental=False,
52 52 ):
53 53 self.section = section
54 54 self.name = name
55 55 self.default = default
56 56 self.alias = list(alias)
57 57 self.generic = generic
58 58 self.priority = priority
59 59 self.experimental = experimental
60 60 self._re = None
61 61 if generic:
62 62 self._re = re.compile(self.name)
63 63
64 64
65 65 class itemregister(dict):
66 66 """A specialized dictionary that can handle wild-card selection"""
67 67
68 68 def __init__(self):
69 69 super(itemregister, self).__init__()
70 70 self._generics = set()
71 71
72 72 def update(self, other):
73 73 super(itemregister, self).update(other)
74 74 self._generics.update(other._generics)
75 75
76 76 def __setitem__(self, key, item):
77 77 super(itemregister, self).__setitem__(key, item)
78 78 if item.generic:
79 79 self._generics.add(item)
80 80
81 81 def get(self, key):
82 82 baseitem = super(itemregister, self).get(key)
83 83 if baseitem is not None and not baseitem.generic:
84 84 return baseitem
85 85
86 86 # search for a matching generic item
87 87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
88 88 for item in generics:
89 89 # we use 'match' instead of 'search' to make the matching simpler
90 90 # for people unfamiliar with regular expression. Having the match
91 91 # rooted to the start of the string will produce less surprising
92 92 # result for user writing simple regex for sub-attribute.
93 93 #
94 94 # For example using "color\..*" match produces an unsurprising
95 95 # result, while using search could suddenly match apparently
96 96 # unrelated configuration that happens to contains "color."
97 97 # anywhere. This is a tradeoff where we favor requiring ".*" on
98 98 # some match to avoid the need to prefix most pattern with "^".
99 99 # The "^" seems more error prone.
100 100 if item._re.match(key):
101 101 return item
102 102
103 103 return None
104 104
105 105
106 106 coreitems = {}
107 107
108 108
109 109 def _register(configtable, *args, **kwargs):
110 110 item = configitem(*args, **kwargs)
111 111 section = configtable.setdefault(item.section, itemregister())
112 112 if item.name in section:
113 113 msg = b"duplicated config item registration for '%s.%s'"
114 114 raise error.ProgrammingError(msg % (item.section, item.name))
115 115 section[item.name] = item
116 116
117 117
118 118 # special value for case where the default is derived from other values
119 119 dynamicdefault = object()
120 120
121 121 # Registering actual config items
122 122
123 123
124 124 def getitemregister(configtable):
125 125 f = functools.partial(_register, configtable)
126 126 # export pseudo enum as configitem.*
127 127 f.dynamicdefault = dynamicdefault
128 128 return f
129 129
130 130
131 131 coreconfigitem = getitemregister(coreitems)
132 132
133 133
134 134 def _registerdiffopts(section, configprefix=b''):
135 135 coreconfigitem(
136 136 section, configprefix + b'nodates', default=False,
137 137 )
138 138 coreconfigitem(
139 139 section, configprefix + b'showfunc', default=False,
140 140 )
141 141 coreconfigitem(
142 142 section, configprefix + b'unified', default=None,
143 143 )
144 144 coreconfigitem(
145 145 section, configprefix + b'git', default=False,
146 146 )
147 147 coreconfigitem(
148 148 section, configprefix + b'ignorews', default=False,
149 149 )
150 150 coreconfigitem(
151 151 section, configprefix + b'ignorewsamount', default=False,
152 152 )
153 153 coreconfigitem(
154 154 section, configprefix + b'ignoreblanklines', default=False,
155 155 )
156 156 coreconfigitem(
157 157 section, configprefix + b'ignorewseol', default=False,
158 158 )
159 159 coreconfigitem(
160 160 section, configprefix + b'nobinary', default=False,
161 161 )
162 162 coreconfigitem(
163 163 section, configprefix + b'noprefix', default=False,
164 164 )
165 165 coreconfigitem(
166 166 section, configprefix + b'word-diff', default=False,
167 167 )
168 168
169 169
170 170 coreconfigitem(
171 171 b'alias', b'.*', default=dynamicdefault, generic=True,
172 172 )
173 173 coreconfigitem(
174 174 b'auth', b'cookiefile', default=None,
175 175 )
176 176 _registerdiffopts(section=b'annotate')
177 177 # bookmarks.pushing: internal hack for discovery
178 178 coreconfigitem(
179 179 b'bookmarks', b'pushing', default=list,
180 180 )
181 181 # bundle.mainreporoot: internal hack for bundlerepo
182 182 coreconfigitem(
183 183 b'bundle', b'mainreporoot', default=b'',
184 184 )
185 185 coreconfigitem(
186 186 b'censor', b'policy', default=b'abort', experimental=True,
187 187 )
188 188 coreconfigitem(
189 189 b'chgserver', b'idletimeout', default=3600,
190 190 )
191 191 coreconfigitem(
192 192 b'chgserver', b'skiphash', default=False,
193 193 )
194 194 coreconfigitem(
195 195 b'cmdserver', b'log', default=None,
196 196 )
197 197 coreconfigitem(
198 198 b'cmdserver', b'max-log-files', default=7,
199 199 )
200 200 coreconfigitem(
201 201 b'cmdserver', b'max-log-size', default=b'1 MB',
202 202 )
203 203 coreconfigitem(
204 204 b'cmdserver', b'max-repo-cache', default=0, experimental=True,
205 205 )
206 206 coreconfigitem(
207 207 b'cmdserver', b'message-encodings', default=list, experimental=True,
208 208 )
209 209 coreconfigitem(
210 210 b'cmdserver',
211 211 b'track-log',
212 212 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
213 213 )
214 214 coreconfigitem(
215 215 b'color', b'.*', default=None, generic=True,
216 216 )
217 217 coreconfigitem(
218 218 b'color', b'mode', default=b'auto',
219 219 )
220 220 coreconfigitem(
221 221 b'color', b'pagermode', default=dynamicdefault,
222 222 )
223 223 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
224 224 coreconfigitem(
225 225 b'commands', b'commit.post-status', default=False,
226 226 )
227 227 coreconfigitem(
228 228 b'commands', b'grep.all-files', default=False, experimental=True,
229 229 )
230 230 coreconfigitem(
231 231 b'commands', b'merge.require-rev', default=False,
232 232 )
233 233 coreconfigitem(
234 234 b'commands', b'push.require-revs', default=False,
235 235 )
236 236 coreconfigitem(
237 237 b'commands', b'resolve.confirm', default=False,
238 238 )
239 239 coreconfigitem(
240 240 b'commands', b'resolve.explicit-re-merge', default=False,
241 241 )
242 242 coreconfigitem(
243 243 b'commands', b'resolve.mark-check', default=b'none',
244 244 )
245 245 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
246 246 coreconfigitem(
247 247 b'commands', b'show.aliasprefix', default=list,
248 248 )
249 249 coreconfigitem(
250 250 b'commands', b'status.relative', default=False,
251 251 )
252 252 coreconfigitem(
253 253 b'commands', b'status.skipstates', default=[], experimental=True,
254 254 )
255 255 coreconfigitem(
256 256 b'commands', b'status.terse', default=b'',
257 257 )
258 258 coreconfigitem(
259 259 b'commands', b'status.verbose', default=False,
260 260 )
261 261 coreconfigitem(
262 262 b'commands', b'update.check', default=None,
263 263 )
264 264 coreconfigitem(
265 265 b'commands', b'update.requiredest', default=False,
266 266 )
267 267 coreconfigitem(
268 268 b'committemplate', b'.*', default=None, generic=True,
269 269 )
270 270 coreconfigitem(
271 271 b'convert', b'bzr.saverev', default=True,
272 272 )
273 273 coreconfigitem(
274 274 b'convert', b'cvsps.cache', default=True,
275 275 )
276 276 coreconfigitem(
277 277 b'convert', b'cvsps.fuzz', default=60,
278 278 )
279 279 coreconfigitem(
280 280 b'convert', b'cvsps.logencoding', default=None,
281 281 )
282 282 coreconfigitem(
283 283 b'convert', b'cvsps.mergefrom', default=None,
284 284 )
285 285 coreconfigitem(
286 286 b'convert', b'cvsps.mergeto', default=None,
287 287 )
288 288 coreconfigitem(
289 289 b'convert', b'git.committeractions', default=lambda: [b'messagedifferent'],
290 290 )
291 291 coreconfigitem(
292 292 b'convert', b'git.extrakeys', default=list,
293 293 )
294 294 coreconfigitem(
295 295 b'convert', b'git.findcopiesharder', default=False,
296 296 )
297 297 coreconfigitem(
298 298 b'convert', b'git.remoteprefix', default=b'remote',
299 299 )
300 300 coreconfigitem(
301 301 b'convert', b'git.renamelimit', default=400,
302 302 )
303 303 coreconfigitem(
304 304 b'convert', b'git.saverev', default=True,
305 305 )
306 306 coreconfigitem(
307 307 b'convert', b'git.similarity', default=50,
308 308 )
309 309 coreconfigitem(
310 310 b'convert', b'git.skipsubmodules', default=False,
311 311 )
312 312 coreconfigitem(
313 313 b'convert', b'hg.clonebranches', default=False,
314 314 )
315 315 coreconfigitem(
316 316 b'convert', b'hg.ignoreerrors', default=False,
317 317 )
318 318 coreconfigitem(
319 319 b'convert', b'hg.preserve-hash', default=False,
320 320 )
321 321 coreconfigitem(
322 322 b'convert', b'hg.revs', default=None,
323 323 )
324 324 coreconfigitem(
325 325 b'convert', b'hg.saverev', default=False,
326 326 )
327 327 coreconfigitem(
328 328 b'convert', b'hg.sourcename', default=None,
329 329 )
330 330 coreconfigitem(
331 331 b'convert', b'hg.startrev', default=None,
332 332 )
333 333 coreconfigitem(
334 334 b'convert', b'hg.tagsbranch', default=b'default',
335 335 )
336 336 coreconfigitem(
337 337 b'convert', b'hg.usebranchnames', default=True,
338 338 )
339 339 coreconfigitem(
340 340 b'convert', b'ignoreancestorcheck', default=False, experimental=True,
341 341 )
342 342 coreconfigitem(
343 343 b'convert', b'localtimezone', default=False,
344 344 )
345 345 coreconfigitem(
346 346 b'convert', b'p4.encoding', default=dynamicdefault,
347 347 )
348 348 coreconfigitem(
349 349 b'convert', b'p4.startrev', default=0,
350 350 )
351 351 coreconfigitem(
352 352 b'convert', b'skiptags', default=False,
353 353 )
354 354 coreconfigitem(
355 355 b'convert', b'svn.debugsvnlog', default=True,
356 356 )
357 357 coreconfigitem(
358 358 b'convert', b'svn.trunk', default=None,
359 359 )
360 360 coreconfigitem(
361 361 b'convert', b'svn.tags', default=None,
362 362 )
363 363 coreconfigitem(
364 364 b'convert', b'svn.branches', default=None,
365 365 )
366 366 coreconfigitem(
367 367 b'convert', b'svn.startrev', default=0,
368 368 )
369 369 coreconfigitem(
370 370 b'debug', b'dirstate.delaywrite', default=0,
371 371 )
372 372 coreconfigitem(
373 373 b'defaults', b'.*', default=None, generic=True,
374 374 )
375 375 coreconfigitem(
376 376 b'devel', b'all-warnings', default=False,
377 377 )
378 378 coreconfigitem(
379 379 b'devel', b'bundle2.debug', default=False,
380 380 )
381 381 coreconfigitem(
382 382 b'devel', b'bundle.delta', default=b'',
383 383 )
384 384 coreconfigitem(
385 385 b'devel', b'cache-vfs', default=None,
386 386 )
387 387 coreconfigitem(
388 388 b'devel', b'check-locks', default=False,
389 389 )
390 390 coreconfigitem(
391 391 b'devel', b'check-relroot', default=False,
392 392 )
393 393 coreconfigitem(
394 394 b'devel', b'default-date', default=None,
395 395 )
396 396 coreconfigitem(
397 397 b'devel', b'deprec-warn', default=False,
398 398 )
399 399 coreconfigitem(
400 400 b'devel', b'disableloaddefaultcerts', default=False,
401 401 )
402 402 coreconfigitem(
403 403 b'devel', b'warn-empty-changegroup', default=False,
404 404 )
405 405 coreconfigitem(
406 406 b'devel', b'legacy.exchange', default=list,
407 407 )
408 408 # TODO before getting `persistent-nodemap` out of experimental
409 409 #
410 # * regenerate a new nodemap when the unused/total ration is to high
411 410 # * decide for a "status" of the persistent nodemap and associated location
412 411 # - part of the store next the revlog itself (new requirements)
413 412 # - part of the cache directory
414 413 # - part of an `index` directory
415 414 # (https://www.mercurial-scm.org/wiki/ComputedIndexPlan)
416 415 # * do we want to use this for more than just changelog? if so we need:
417 416 # - simpler "pending" logic for them
418 417 # - double check the memory story (we dont want to keep all revlog in memory)
419 418 # - think about the naming scheme if we are in "cache"
420 419 # * increment the version format to "1" and freeze it.
421 420 coreconfigitem(
422 421 b'devel', b'persistent-nodemap', default=False,
423 422 )
424 423 coreconfigitem(
425 424 b'devel', b'servercafile', default=b'',
426 425 )
427 426 coreconfigitem(
428 427 b'devel', b'serverexactprotocol', default=b'',
429 428 )
430 429 coreconfigitem(
431 430 b'devel', b'serverrequirecert', default=False,
432 431 )
433 432 coreconfigitem(
434 433 b'devel', b'strip-obsmarkers', default=True,
435 434 )
436 435 coreconfigitem(
437 436 b'devel', b'warn-config', default=None,
438 437 )
439 438 coreconfigitem(
440 439 b'devel', b'warn-config-default', default=None,
441 440 )
442 441 coreconfigitem(
443 442 b'devel', b'user.obsmarker', default=None,
444 443 )
445 444 coreconfigitem(
446 445 b'devel', b'warn-config-unknown', default=None,
447 446 )
448 447 coreconfigitem(
449 448 b'devel', b'debug.copies', default=False,
450 449 )
451 450 coreconfigitem(
452 451 b'devel', b'debug.extensions', default=False,
453 452 )
454 453 coreconfigitem(
455 454 b'devel', b'debug.repo-filters', default=False,
456 455 )
457 456 coreconfigitem(
458 457 b'devel', b'debug.peer-request', default=False,
459 458 )
460 459 coreconfigitem(
461 460 b'devel', b'discovery.randomize', default=True,
462 461 )
463 462 _registerdiffopts(section=b'diff')
464 463 coreconfigitem(
465 464 b'email', b'bcc', default=None,
466 465 )
467 466 coreconfigitem(
468 467 b'email', b'cc', default=None,
469 468 )
470 469 coreconfigitem(
471 470 b'email', b'charsets', default=list,
472 471 )
473 472 coreconfigitem(
474 473 b'email', b'from', default=None,
475 474 )
476 475 coreconfigitem(
477 476 b'email', b'method', default=b'smtp',
478 477 )
479 478 coreconfigitem(
480 479 b'email', b'reply-to', default=None,
481 480 )
482 481 coreconfigitem(
483 482 b'email', b'to', default=None,
484 483 )
485 484 coreconfigitem(
486 485 b'experimental', b'archivemetatemplate', default=dynamicdefault,
487 486 )
488 487 coreconfigitem(
489 488 b'experimental', b'auto-publish', default=b'publish',
490 489 )
491 490 coreconfigitem(
492 491 b'experimental', b'bundle-phases', default=False,
493 492 )
494 493 coreconfigitem(
495 494 b'experimental', b'bundle2-advertise', default=True,
496 495 )
497 496 coreconfigitem(
498 497 b'experimental', b'bundle2-output-capture', default=False,
499 498 )
500 499 coreconfigitem(
501 500 b'experimental', b'bundle2.pushback', default=False,
502 501 )
503 502 coreconfigitem(
504 503 b'experimental', b'bundle2lazylocking', default=False,
505 504 )
506 505 coreconfigitem(
507 506 b'experimental', b'bundlecomplevel', default=None,
508 507 )
509 508 coreconfigitem(
510 509 b'experimental', b'bundlecomplevel.bzip2', default=None,
511 510 )
512 511 coreconfigitem(
513 512 b'experimental', b'bundlecomplevel.gzip', default=None,
514 513 )
515 514 coreconfigitem(
516 515 b'experimental', b'bundlecomplevel.none', default=None,
517 516 )
518 517 coreconfigitem(
519 518 b'experimental', b'bundlecomplevel.zstd', default=None,
520 519 )
521 520 coreconfigitem(
522 521 b'experimental', b'changegroup3', default=False,
523 522 )
524 523 coreconfigitem(
525 524 b'experimental', b'cleanup-as-archived', default=False,
526 525 )
527 526 coreconfigitem(
528 527 b'experimental', b'clientcompressionengines', default=list,
529 528 )
530 529 coreconfigitem(
531 530 b'experimental', b'copytrace', default=b'on',
532 531 )
533 532 coreconfigitem(
534 533 b'experimental', b'copytrace.movecandidateslimit', default=100,
535 534 )
536 535 coreconfigitem(
537 536 b'experimental', b'copytrace.sourcecommitlimit', default=100,
538 537 )
539 538 coreconfigitem(
540 539 b'experimental', b'copies.read-from', default=b"filelog-only",
541 540 )
542 541 coreconfigitem(
543 542 b'experimental', b'copies.write-to', default=b'filelog-only',
544 543 )
545 544 coreconfigitem(
546 545 b'experimental', b'crecordtest', default=None,
547 546 )
548 547 coreconfigitem(
549 548 b'experimental', b'directaccess', default=False,
550 549 )
551 550 coreconfigitem(
552 551 b'experimental', b'directaccess.revnums', default=False,
553 552 )
554 553 coreconfigitem(
555 554 b'experimental', b'editortmpinhg', default=False,
556 555 )
557 556 coreconfigitem(
558 557 b'experimental', b'evolution', default=list,
559 558 )
560 559 coreconfigitem(
561 560 b'experimental',
562 561 b'evolution.allowdivergence',
563 562 default=False,
564 563 alias=[(b'experimental', b'allowdivergence')],
565 564 )
566 565 coreconfigitem(
567 566 b'experimental', b'evolution.allowunstable', default=None,
568 567 )
569 568 coreconfigitem(
570 569 b'experimental', b'evolution.createmarkers', default=None,
571 570 )
572 571 coreconfigitem(
573 572 b'experimental',
574 573 b'evolution.effect-flags',
575 574 default=True,
576 575 alias=[(b'experimental', b'effect-flags')],
577 576 )
578 577 coreconfigitem(
579 578 b'experimental', b'evolution.exchange', default=None,
580 579 )
581 580 coreconfigitem(
582 581 b'experimental', b'evolution.bundle-obsmarker', default=False,
583 582 )
584 583 coreconfigitem(
585 584 b'experimental', b'log.topo', default=False,
586 585 )
587 586 coreconfigitem(
588 587 b'experimental', b'evolution.report-instabilities', default=True,
589 588 )
590 589 coreconfigitem(
591 590 b'experimental', b'evolution.track-operation', default=True,
592 591 )
593 592 # repo-level config to exclude a revset visibility
594 593 #
595 594 # The target use case is to use `share` to expose different subset of the same
596 595 # repository, especially server side. See also `server.view`.
597 596 coreconfigitem(
598 597 b'experimental', b'extra-filter-revs', default=None,
599 598 )
600 599 coreconfigitem(
601 600 b'experimental', b'maxdeltachainspan', default=-1,
602 601 )
603 602 coreconfigitem(
604 603 b'experimental', b'mergetempdirprefix', default=None,
605 604 )
606 605 coreconfigitem(
607 606 b'experimental', b'mmapindexthreshold', default=None,
608 607 )
609 608 coreconfigitem(
610 609 b'experimental', b'narrow', default=False,
611 610 )
612 611 coreconfigitem(
613 612 b'experimental', b'nonnormalparanoidcheck', default=False,
614 613 )
615 614 coreconfigitem(
616 615 b'experimental', b'exportableenviron', default=list,
617 616 )
618 617 coreconfigitem(
619 618 b'experimental', b'extendedheader.index', default=None,
620 619 )
621 620 coreconfigitem(
622 621 b'experimental', b'extendedheader.similarity', default=False,
623 622 )
624 623 coreconfigitem(
625 624 b'experimental', b'graphshorten', default=False,
626 625 )
627 626 coreconfigitem(
628 627 b'experimental', b'graphstyle.parent', default=dynamicdefault,
629 628 )
630 629 coreconfigitem(
631 630 b'experimental', b'graphstyle.missing', default=dynamicdefault,
632 631 )
633 632 coreconfigitem(
634 633 b'experimental', b'graphstyle.grandparent', default=dynamicdefault,
635 634 )
636 635 coreconfigitem(
637 636 b'experimental', b'hook-track-tags', default=False,
638 637 )
639 638 coreconfigitem(
640 639 b'experimental', b'httppeer.advertise-v2', default=False,
641 640 )
642 641 coreconfigitem(
643 642 b'experimental', b'httppeer.v2-encoder-order', default=None,
644 643 )
645 644 coreconfigitem(
646 645 b'experimental', b'httppostargs', default=False,
647 646 )
648 647 coreconfigitem(
649 648 b'experimental', b'mergedriver', default=None,
650 649 )
651 650 coreconfigitem(b'experimental', b'nointerrupt', default=False)
652 651 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
653 652
654 653 coreconfigitem(
655 654 b'experimental', b'obsmarkers-exchange-debug', default=False,
656 655 )
657 656 coreconfigitem(
658 657 b'experimental', b'remotenames', default=False,
659 658 )
660 659 coreconfigitem(
661 660 b'experimental', b'removeemptydirs', default=True,
662 661 )
663 662 coreconfigitem(
664 663 b'experimental', b'revert.interactive.select-to-keep', default=False,
665 664 )
666 665 coreconfigitem(
667 666 b'experimental', b'revisions.prefixhexnode', default=False,
668 667 )
669 668 coreconfigitem(
670 669 b'experimental', b'revlogv2', default=None,
671 670 )
672 671 coreconfigitem(
673 672 b'experimental', b'revisions.disambiguatewithin', default=None,
674 673 )
675 674 coreconfigitem(
676 675 b'experimental', b'rust.index', default=False,
677 676 )
678 677 coreconfigitem(
679 678 b'experimental', b'exp-persistent-nodemap', default=False,
680 679 )
681 680 coreconfigitem(
682 681 b'experimental', b'exp-persistent-nodemap.mmap', default=True,
683 682 )
684 683 coreconfigitem(
685 684 b'experimental', b'server.filesdata.recommended-batch-size', default=50000,
686 685 )
687 686 coreconfigitem(
688 687 b'experimental',
689 688 b'server.manifestdata.recommended-batch-size',
690 689 default=100000,
691 690 )
692 691 coreconfigitem(
693 692 b'experimental', b'server.stream-narrow-clones', default=False,
694 693 )
695 694 coreconfigitem(
696 695 b'experimental', b'single-head-per-branch', default=False,
697 696 )
698 697 coreconfigitem(
699 698 b'experimental',
700 699 b'single-head-per-branch:account-closed-heads',
701 700 default=False,
702 701 )
703 702 coreconfigitem(
704 703 b'experimental', b'sshserver.support-v2', default=False,
705 704 )
706 705 coreconfigitem(
707 706 b'experimental', b'sparse-read', default=False,
708 707 )
709 708 coreconfigitem(
710 709 b'experimental', b'sparse-read.density-threshold', default=0.50,
711 710 )
712 711 coreconfigitem(
713 712 b'experimental', b'sparse-read.min-gap-size', default=b'65K',
714 713 )
715 714 coreconfigitem(
716 715 b'experimental', b'treemanifest', default=False,
717 716 )
718 717 coreconfigitem(
719 718 b'experimental', b'update.atomic-file', default=False,
720 719 )
721 720 coreconfigitem(
722 721 b'experimental', b'sshpeer.advertise-v2', default=False,
723 722 )
724 723 coreconfigitem(
725 724 b'experimental', b'web.apiserver', default=False,
726 725 )
727 726 coreconfigitem(
728 727 b'experimental', b'web.api.http-v2', default=False,
729 728 )
730 729 coreconfigitem(
731 730 b'experimental', b'web.api.debugreflect', default=False,
732 731 )
733 732 coreconfigitem(
734 733 b'experimental', b'worker.wdir-get-thread-safe', default=False,
735 734 )
736 735 coreconfigitem(
737 736 b'experimental', b'worker.repository-upgrade', default=False,
738 737 )
739 738 coreconfigitem(
740 739 b'experimental', b'xdiff', default=False,
741 740 )
742 741 coreconfigitem(
743 742 b'extensions', b'.*', default=None, generic=True,
744 743 )
745 744 coreconfigitem(
746 745 b'extdata', b'.*', default=None, generic=True,
747 746 )
748 747 coreconfigitem(
749 748 b'format', b'bookmarks-in-store', default=False,
750 749 )
751 750 coreconfigitem(
752 751 b'format', b'chunkcachesize', default=None, experimental=True,
753 752 )
754 753 coreconfigitem(
755 754 b'format', b'dotencode', default=True,
756 755 )
757 756 coreconfigitem(
758 757 b'format', b'generaldelta', default=False, experimental=True,
759 758 )
760 759 coreconfigitem(
761 760 b'format', b'manifestcachesize', default=None, experimental=True,
762 761 )
763 762 coreconfigitem(
764 763 b'format', b'maxchainlen', default=dynamicdefault, experimental=True,
765 764 )
766 765 coreconfigitem(
767 766 b'format', b'obsstore-version', default=None,
768 767 )
769 768 coreconfigitem(
770 769 b'format', b'sparse-revlog', default=True,
771 770 )
772 771 coreconfigitem(
773 772 b'format',
774 773 b'revlog-compression',
775 774 default=lambda: [b'zlib'],
776 775 alias=[(b'experimental', b'format.compression')],
777 776 )
778 777 coreconfigitem(
779 778 b'format', b'usefncache', default=True,
780 779 )
781 780 coreconfigitem(
782 781 b'format', b'usegeneraldelta', default=True,
783 782 )
784 783 coreconfigitem(
785 784 b'format', b'usestore', default=True,
786 785 )
787 786 coreconfigitem(
788 787 b'format',
789 788 b'exp-use-copies-side-data-changeset',
790 789 default=False,
791 790 experimental=True,
792 791 )
793 792 coreconfigitem(
794 793 b'format', b'exp-use-side-data', default=False, experimental=True,
795 794 )
796 795 coreconfigitem(
797 796 b'format', b'internal-phase', default=False, experimental=True,
798 797 )
799 798 coreconfigitem(
800 799 b'fsmonitor', b'warn_when_unused', default=True,
801 800 )
802 801 coreconfigitem(
803 802 b'fsmonitor', b'warn_update_file_count', default=50000,
804 803 )
805 804 coreconfigitem(
806 805 b'help', br'hidden-command\..*', default=False, generic=True,
807 806 )
808 807 coreconfigitem(
809 808 b'help', br'hidden-topic\..*', default=False, generic=True,
810 809 )
811 810 coreconfigitem(
812 811 b'hooks', b'.*', default=dynamicdefault, generic=True,
813 812 )
814 813 coreconfigitem(
815 814 b'hgweb-paths', b'.*', default=list, generic=True,
816 815 )
817 816 coreconfigitem(
818 817 b'hostfingerprints', b'.*', default=list, generic=True,
819 818 )
820 819 coreconfigitem(
821 820 b'hostsecurity', b'ciphers', default=None,
822 821 )
823 822 coreconfigitem(
824 823 b'hostsecurity', b'disabletls10warning', default=False,
825 824 )
826 825 coreconfigitem(
827 826 b'hostsecurity', b'minimumprotocol', default=dynamicdefault,
828 827 )
829 828 coreconfigitem(
830 829 b'hostsecurity',
831 830 b'.*:minimumprotocol$',
832 831 default=dynamicdefault,
833 832 generic=True,
834 833 )
835 834 coreconfigitem(
836 835 b'hostsecurity', b'.*:ciphers$', default=dynamicdefault, generic=True,
837 836 )
838 837 coreconfigitem(
839 838 b'hostsecurity', b'.*:fingerprints$', default=list, generic=True,
840 839 )
841 840 coreconfigitem(
842 841 b'hostsecurity', b'.*:verifycertsfile$', default=None, generic=True,
843 842 )
844 843
845 844 coreconfigitem(
846 845 b'http_proxy', b'always', default=False,
847 846 )
848 847 coreconfigitem(
849 848 b'http_proxy', b'host', default=None,
850 849 )
851 850 coreconfigitem(
852 851 b'http_proxy', b'no', default=list,
853 852 )
854 853 coreconfigitem(
855 854 b'http_proxy', b'passwd', default=None,
856 855 )
857 856 coreconfigitem(
858 857 b'http_proxy', b'user', default=None,
859 858 )
860 859
861 860 coreconfigitem(
862 861 b'http', b'timeout', default=None,
863 862 )
864 863
865 864 coreconfigitem(
866 865 b'logtoprocess', b'commandexception', default=None,
867 866 )
868 867 coreconfigitem(
869 868 b'logtoprocess', b'commandfinish', default=None,
870 869 )
871 870 coreconfigitem(
872 871 b'logtoprocess', b'command', default=None,
873 872 )
874 873 coreconfigitem(
875 874 b'logtoprocess', b'develwarn', default=None,
876 875 )
877 876 coreconfigitem(
878 877 b'logtoprocess', b'uiblocked', default=None,
879 878 )
880 879 coreconfigitem(
881 880 b'merge', b'checkunknown', default=b'abort',
882 881 )
883 882 coreconfigitem(
884 883 b'merge', b'checkignored', default=b'abort',
885 884 )
886 885 coreconfigitem(
887 886 b'experimental', b'merge.checkpathconflicts', default=False,
888 887 )
889 888 coreconfigitem(
890 889 b'merge', b'followcopies', default=True,
891 890 )
892 891 coreconfigitem(
893 892 b'merge', b'on-failure', default=b'continue',
894 893 )
895 894 coreconfigitem(
896 895 b'merge', b'preferancestor', default=lambda: [b'*'], experimental=True,
897 896 )
898 897 coreconfigitem(
899 898 b'merge', b'strict-capability-check', default=False,
900 899 )
901 900 coreconfigitem(
902 901 b'merge-tools', b'.*', default=None, generic=True,
903 902 )
904 903 coreconfigitem(
905 904 b'merge-tools',
906 905 br'.*\.args$',
907 906 default=b"$local $base $other",
908 907 generic=True,
909 908 priority=-1,
910 909 )
911 910 coreconfigitem(
912 911 b'merge-tools', br'.*\.binary$', default=False, generic=True, priority=-1,
913 912 )
914 913 coreconfigitem(
915 914 b'merge-tools', br'.*\.check$', default=list, generic=True, priority=-1,
916 915 )
917 916 coreconfigitem(
918 917 b'merge-tools',
919 918 br'.*\.checkchanged$',
920 919 default=False,
921 920 generic=True,
922 921 priority=-1,
923 922 )
924 923 coreconfigitem(
925 924 b'merge-tools',
926 925 br'.*\.executable$',
927 926 default=dynamicdefault,
928 927 generic=True,
929 928 priority=-1,
930 929 )
931 930 coreconfigitem(
932 931 b'merge-tools', br'.*\.fixeol$', default=False, generic=True, priority=-1,
933 932 )
934 933 coreconfigitem(
935 934 b'merge-tools', br'.*\.gui$', default=False, generic=True, priority=-1,
936 935 )
937 936 coreconfigitem(
938 937 b'merge-tools',
939 938 br'.*\.mergemarkers$',
940 939 default=b'basic',
941 940 generic=True,
942 941 priority=-1,
943 942 )
944 943 coreconfigitem(
945 944 b'merge-tools',
946 945 br'.*\.mergemarkertemplate$',
947 946 default=dynamicdefault, # take from ui.mergemarkertemplate
948 947 generic=True,
949 948 priority=-1,
950 949 )
951 950 coreconfigitem(
952 951 b'merge-tools', br'.*\.priority$', default=0, generic=True, priority=-1,
953 952 )
954 953 coreconfigitem(
955 954 b'merge-tools',
956 955 br'.*\.premerge$',
957 956 default=dynamicdefault,
958 957 generic=True,
959 958 priority=-1,
960 959 )
961 960 coreconfigitem(
962 961 b'merge-tools', br'.*\.symlink$', default=False, generic=True, priority=-1,
963 962 )
964 963 coreconfigitem(
965 964 b'pager', b'attend-.*', default=dynamicdefault, generic=True,
966 965 )
967 966 coreconfigitem(
968 967 b'pager', b'ignore', default=list,
969 968 )
970 969 coreconfigitem(
971 970 b'pager', b'pager', default=dynamicdefault,
972 971 )
973 972 coreconfigitem(
974 973 b'patch', b'eol', default=b'strict',
975 974 )
976 975 coreconfigitem(
977 976 b'patch', b'fuzz', default=2,
978 977 )
979 978 coreconfigitem(
980 979 b'paths', b'default', default=None,
981 980 )
982 981 coreconfigitem(
983 982 b'paths', b'default-push', default=None,
984 983 )
985 984 coreconfigitem(
986 985 b'paths', b'.*', default=None, generic=True,
987 986 )
988 987 coreconfigitem(
989 988 b'phases', b'checksubrepos', default=b'follow',
990 989 )
991 990 coreconfigitem(
992 991 b'phases', b'new-commit', default=b'draft',
993 992 )
994 993 coreconfigitem(
995 994 b'phases', b'publish', default=True,
996 995 )
997 996 coreconfigitem(
998 997 b'profiling', b'enabled', default=False,
999 998 )
1000 999 coreconfigitem(
1001 1000 b'profiling', b'format', default=b'text',
1002 1001 )
1003 1002 coreconfigitem(
1004 1003 b'profiling', b'freq', default=1000,
1005 1004 )
1006 1005 coreconfigitem(
1007 1006 b'profiling', b'limit', default=30,
1008 1007 )
1009 1008 coreconfigitem(
1010 1009 b'profiling', b'nested', default=0,
1011 1010 )
1012 1011 coreconfigitem(
1013 1012 b'profiling', b'output', default=None,
1014 1013 )
1015 1014 coreconfigitem(
1016 1015 b'profiling', b'showmax', default=0.999,
1017 1016 )
1018 1017 coreconfigitem(
1019 1018 b'profiling', b'showmin', default=dynamicdefault,
1020 1019 )
1021 1020 coreconfigitem(
1022 1021 b'profiling', b'showtime', default=True,
1023 1022 )
1024 1023 coreconfigitem(
1025 1024 b'profiling', b'sort', default=b'inlinetime',
1026 1025 )
1027 1026 coreconfigitem(
1028 1027 b'profiling', b'statformat', default=b'hotpath',
1029 1028 )
1030 1029 coreconfigitem(
1031 1030 b'profiling', b'time-track', default=dynamicdefault,
1032 1031 )
1033 1032 coreconfigitem(
1034 1033 b'profiling', b'type', default=b'stat',
1035 1034 )
1036 1035 coreconfigitem(
1037 1036 b'progress', b'assume-tty', default=False,
1038 1037 )
1039 1038 coreconfigitem(
1040 1039 b'progress', b'changedelay', default=1,
1041 1040 )
1042 1041 coreconfigitem(
1043 1042 b'progress', b'clear-complete', default=True,
1044 1043 )
1045 1044 coreconfigitem(
1046 1045 b'progress', b'debug', default=False,
1047 1046 )
1048 1047 coreconfigitem(
1049 1048 b'progress', b'delay', default=3,
1050 1049 )
1051 1050 coreconfigitem(
1052 1051 b'progress', b'disable', default=False,
1053 1052 )
1054 1053 coreconfigitem(
1055 1054 b'progress', b'estimateinterval', default=60.0,
1056 1055 )
1057 1056 coreconfigitem(
1058 1057 b'progress',
1059 1058 b'format',
1060 1059 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1061 1060 )
1062 1061 coreconfigitem(
1063 1062 b'progress', b'refresh', default=0.1,
1064 1063 )
1065 1064 coreconfigitem(
1066 1065 b'progress', b'width', default=dynamicdefault,
1067 1066 )
1068 1067 coreconfigitem(
1069 1068 b'pull', b'confirm', default=False,
1070 1069 )
1071 1070 coreconfigitem(
1072 1071 b'push', b'pushvars.server', default=False,
1073 1072 )
1074 1073 coreconfigitem(
1075 1074 b'rewrite',
1076 1075 b'backup-bundle',
1077 1076 default=True,
1078 1077 alias=[(b'ui', b'history-editing-backup')],
1079 1078 )
1080 1079 coreconfigitem(
1081 1080 b'rewrite', b'update-timestamp', default=False,
1082 1081 )
1083 1082 coreconfigitem(
1084 1083 b'storage', b'new-repo-backend', default=b'revlogv1', experimental=True,
1085 1084 )
1086 1085 coreconfigitem(
1087 1086 b'storage',
1088 1087 b'revlog.optimize-delta-parent-choice',
1089 1088 default=True,
1090 1089 alias=[(b'format', b'aggressivemergedeltas')],
1091 1090 )
1092 1091 coreconfigitem(
1093 1092 b'storage', b'revlog.reuse-external-delta', default=True,
1094 1093 )
1095 1094 coreconfigitem(
1096 1095 b'storage', b'revlog.reuse-external-delta-parent', default=None,
1097 1096 )
1098 1097 coreconfigitem(
1099 1098 b'storage', b'revlog.zlib.level', default=None,
1100 1099 )
1101 1100 coreconfigitem(
1102 1101 b'storage', b'revlog.zstd.level', default=None,
1103 1102 )
1104 1103 coreconfigitem(
1105 1104 b'server', b'bookmarks-pushkey-compat', default=True,
1106 1105 )
1107 1106 coreconfigitem(
1108 1107 b'server', b'bundle1', default=True,
1109 1108 )
1110 1109 coreconfigitem(
1111 1110 b'server', b'bundle1gd', default=None,
1112 1111 )
1113 1112 coreconfigitem(
1114 1113 b'server', b'bundle1.pull', default=None,
1115 1114 )
1116 1115 coreconfigitem(
1117 1116 b'server', b'bundle1gd.pull', default=None,
1118 1117 )
1119 1118 coreconfigitem(
1120 1119 b'server', b'bundle1.push', default=None,
1121 1120 )
1122 1121 coreconfigitem(
1123 1122 b'server', b'bundle1gd.push', default=None,
1124 1123 )
1125 1124 coreconfigitem(
1126 1125 b'server',
1127 1126 b'bundle2.stream',
1128 1127 default=True,
1129 1128 alias=[(b'experimental', b'bundle2.stream')],
1130 1129 )
1131 1130 coreconfigitem(
1132 1131 b'server', b'compressionengines', default=list,
1133 1132 )
1134 1133 coreconfigitem(
1135 1134 b'server', b'concurrent-push-mode', default=b'check-related',
1136 1135 )
1137 1136 coreconfigitem(
1138 1137 b'server', b'disablefullbundle', default=False,
1139 1138 )
1140 1139 coreconfigitem(
1141 1140 b'server', b'maxhttpheaderlen', default=1024,
1142 1141 )
1143 1142 coreconfigitem(
1144 1143 b'server', b'pullbundle', default=False,
1145 1144 )
1146 1145 coreconfigitem(
1147 1146 b'server', b'preferuncompressed', default=False,
1148 1147 )
1149 1148 coreconfigitem(
1150 1149 b'server', b'streamunbundle', default=False,
1151 1150 )
1152 1151 coreconfigitem(
1153 1152 b'server', b'uncompressed', default=True,
1154 1153 )
1155 1154 coreconfigitem(
1156 1155 b'server', b'uncompressedallowsecret', default=False,
1157 1156 )
1158 1157 coreconfigitem(
1159 1158 b'server', b'view', default=b'served',
1160 1159 )
1161 1160 coreconfigitem(
1162 1161 b'server', b'validate', default=False,
1163 1162 )
1164 1163 coreconfigitem(
1165 1164 b'server', b'zliblevel', default=-1,
1166 1165 )
1167 1166 coreconfigitem(
1168 1167 b'server', b'zstdlevel', default=3,
1169 1168 )
1170 1169 coreconfigitem(
1171 1170 b'share', b'pool', default=None,
1172 1171 )
1173 1172 coreconfigitem(
1174 1173 b'share', b'poolnaming', default=b'identity',
1175 1174 )
1176 1175 coreconfigitem(
1177 1176 b'shelve', b'maxbackups', default=10,
1178 1177 )
1179 1178 coreconfigitem(
1180 1179 b'smtp', b'host', default=None,
1181 1180 )
1182 1181 coreconfigitem(
1183 1182 b'smtp', b'local_hostname', default=None,
1184 1183 )
1185 1184 coreconfigitem(
1186 1185 b'smtp', b'password', default=None,
1187 1186 )
1188 1187 coreconfigitem(
1189 1188 b'smtp', b'port', default=dynamicdefault,
1190 1189 )
1191 1190 coreconfigitem(
1192 1191 b'smtp', b'tls', default=b'none',
1193 1192 )
1194 1193 coreconfigitem(
1195 1194 b'smtp', b'username', default=None,
1196 1195 )
1197 1196 coreconfigitem(
1198 1197 b'sparse', b'missingwarning', default=True, experimental=True,
1199 1198 )
1200 1199 coreconfigitem(
1201 1200 b'subrepos',
1202 1201 b'allowed',
1203 1202 default=dynamicdefault, # to make backporting simpler
1204 1203 )
1205 1204 coreconfigitem(
1206 1205 b'subrepos', b'hg:allowed', default=dynamicdefault,
1207 1206 )
1208 1207 coreconfigitem(
1209 1208 b'subrepos', b'git:allowed', default=dynamicdefault,
1210 1209 )
1211 1210 coreconfigitem(
1212 1211 b'subrepos', b'svn:allowed', default=dynamicdefault,
1213 1212 )
1214 1213 coreconfigitem(
1215 1214 b'templates', b'.*', default=None, generic=True,
1216 1215 )
1217 1216 coreconfigitem(
1218 1217 b'templateconfig', b'.*', default=dynamicdefault, generic=True,
1219 1218 )
1220 1219 coreconfigitem(
1221 1220 b'trusted', b'groups', default=list,
1222 1221 )
1223 1222 coreconfigitem(
1224 1223 b'trusted', b'users', default=list,
1225 1224 )
1226 1225 coreconfigitem(
1227 1226 b'ui', b'_usedassubrepo', default=False,
1228 1227 )
1229 1228 coreconfigitem(
1230 1229 b'ui', b'allowemptycommit', default=False,
1231 1230 )
1232 1231 coreconfigitem(
1233 1232 b'ui', b'archivemeta', default=True,
1234 1233 )
1235 1234 coreconfigitem(
1236 1235 b'ui', b'askusername', default=False,
1237 1236 )
1238 1237 coreconfigitem(
1239 1238 b'ui', b'clonebundlefallback', default=False,
1240 1239 )
1241 1240 coreconfigitem(
1242 1241 b'ui', b'clonebundleprefers', default=list,
1243 1242 )
1244 1243 coreconfigitem(
1245 1244 b'ui', b'clonebundles', default=True,
1246 1245 )
1247 1246 coreconfigitem(
1248 1247 b'ui', b'color', default=b'auto',
1249 1248 )
1250 1249 coreconfigitem(
1251 1250 b'ui', b'commitsubrepos', default=False,
1252 1251 )
1253 1252 coreconfigitem(
1254 1253 b'ui', b'debug', default=False,
1255 1254 )
1256 1255 coreconfigitem(
1257 1256 b'ui', b'debugger', default=None,
1258 1257 )
1259 1258 coreconfigitem(
1260 1259 b'ui', b'editor', default=dynamicdefault,
1261 1260 )
1262 1261 coreconfigitem(
1263 1262 b'ui', b'fallbackencoding', default=None,
1264 1263 )
1265 1264 coreconfigitem(
1266 1265 b'ui', b'forcecwd', default=None,
1267 1266 )
1268 1267 coreconfigitem(
1269 1268 b'ui', b'forcemerge', default=None,
1270 1269 )
1271 1270 coreconfigitem(
1272 1271 b'ui', b'formatdebug', default=False,
1273 1272 )
1274 1273 coreconfigitem(
1275 1274 b'ui', b'formatjson', default=False,
1276 1275 )
1277 1276 coreconfigitem(
1278 1277 b'ui', b'formatted', default=None,
1279 1278 )
1280 1279 coreconfigitem(
1281 1280 b'ui', b'graphnodetemplate', default=None,
1282 1281 )
1283 1282 coreconfigitem(
1284 1283 b'ui', b'interactive', default=None,
1285 1284 )
1286 1285 coreconfigitem(
1287 1286 b'ui', b'interface', default=None,
1288 1287 )
1289 1288 coreconfigitem(
1290 1289 b'ui', b'interface.chunkselector', default=None,
1291 1290 )
1292 1291 coreconfigitem(
1293 1292 b'ui', b'large-file-limit', default=10000000,
1294 1293 )
1295 1294 coreconfigitem(
1296 1295 b'ui', b'logblockedtimes', default=False,
1297 1296 )
1298 1297 coreconfigitem(
1299 1298 b'ui', b'logtemplate', default=None,
1300 1299 )
1301 1300 coreconfigitem(
1302 1301 b'ui', b'merge', default=None,
1303 1302 )
1304 1303 coreconfigitem(
1305 1304 b'ui', b'mergemarkers', default=b'basic',
1306 1305 )
1307 1306 coreconfigitem(
1308 1307 b'ui',
1309 1308 b'mergemarkertemplate',
1310 1309 default=(
1311 1310 b'{node|short} '
1312 1311 b'{ifeq(tags, "tip", "", '
1313 1312 b'ifeq(tags, "", "", "{tags} "))}'
1314 1313 b'{if(bookmarks, "{bookmarks} ")}'
1315 1314 b'{ifeq(branch, "default", "", "{branch} ")}'
1316 1315 b'- {author|user}: {desc|firstline}'
1317 1316 ),
1318 1317 )
1319 1318 coreconfigitem(
1320 1319 b'ui', b'message-output', default=b'stdio',
1321 1320 )
1322 1321 coreconfigitem(
1323 1322 b'ui', b'nontty', default=False,
1324 1323 )
1325 1324 coreconfigitem(
1326 1325 b'ui', b'origbackuppath', default=None,
1327 1326 )
1328 1327 coreconfigitem(
1329 1328 b'ui', b'paginate', default=True,
1330 1329 )
1331 1330 coreconfigitem(
1332 1331 b'ui', b'patch', default=None,
1333 1332 )
1334 1333 coreconfigitem(
1335 1334 b'ui', b'pre-merge-tool-output-template', default=None,
1336 1335 )
1337 1336 coreconfigitem(
1338 1337 b'ui', b'portablefilenames', default=b'warn',
1339 1338 )
1340 1339 coreconfigitem(
1341 1340 b'ui', b'promptecho', default=False,
1342 1341 )
1343 1342 coreconfigitem(
1344 1343 b'ui', b'quiet', default=False,
1345 1344 )
1346 1345 coreconfigitem(
1347 1346 b'ui', b'quietbookmarkmove', default=False,
1348 1347 )
1349 1348 coreconfigitem(
1350 1349 b'ui', b'relative-paths', default=b'legacy',
1351 1350 )
1352 1351 coreconfigitem(
1353 1352 b'ui', b'remotecmd', default=b'hg',
1354 1353 )
1355 1354 coreconfigitem(
1356 1355 b'ui', b'report_untrusted', default=True,
1357 1356 )
1358 1357 coreconfigitem(
1359 1358 b'ui', b'rollback', default=True,
1360 1359 )
1361 1360 coreconfigitem(
1362 1361 b'ui', b'signal-safe-lock', default=True,
1363 1362 )
1364 1363 coreconfigitem(
1365 1364 b'ui', b'slash', default=False,
1366 1365 )
1367 1366 coreconfigitem(
1368 1367 b'ui', b'ssh', default=b'ssh',
1369 1368 )
1370 1369 coreconfigitem(
1371 1370 b'ui', b'ssherrorhint', default=None,
1372 1371 )
1373 1372 coreconfigitem(
1374 1373 b'ui', b'statuscopies', default=False,
1375 1374 )
1376 1375 coreconfigitem(
1377 1376 b'ui', b'strict', default=False,
1378 1377 )
1379 1378 coreconfigitem(
1380 1379 b'ui', b'style', default=b'',
1381 1380 )
1382 1381 coreconfigitem(
1383 1382 b'ui', b'supportcontact', default=None,
1384 1383 )
1385 1384 coreconfigitem(
1386 1385 b'ui', b'textwidth', default=78,
1387 1386 )
1388 1387 coreconfigitem(
1389 1388 b'ui', b'timeout', default=b'600',
1390 1389 )
1391 1390 coreconfigitem(
1392 1391 b'ui', b'timeout.warn', default=0,
1393 1392 )
1394 1393 coreconfigitem(
1395 1394 b'ui', b'traceback', default=False,
1396 1395 )
1397 1396 coreconfigitem(
1398 1397 b'ui', b'tweakdefaults', default=False,
1399 1398 )
1400 1399 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
1401 1400 coreconfigitem(
1402 1401 b'ui', b'verbose', default=False,
1403 1402 )
1404 1403 coreconfigitem(
1405 1404 b'verify', b'skipflags', default=None,
1406 1405 )
1407 1406 coreconfigitem(
1408 1407 b'web', b'allowbz2', default=False,
1409 1408 )
1410 1409 coreconfigitem(
1411 1410 b'web', b'allowgz', default=False,
1412 1411 )
1413 1412 coreconfigitem(
1414 1413 b'web', b'allow-pull', alias=[(b'web', b'allowpull')], default=True,
1415 1414 )
1416 1415 coreconfigitem(
1417 1416 b'web', b'allow-push', alias=[(b'web', b'allow_push')], default=list,
1418 1417 )
1419 1418 coreconfigitem(
1420 1419 b'web', b'allowzip', default=False,
1421 1420 )
1422 1421 coreconfigitem(
1423 1422 b'web', b'archivesubrepos', default=False,
1424 1423 )
1425 1424 coreconfigitem(
1426 1425 b'web', b'cache', default=True,
1427 1426 )
1428 1427 coreconfigitem(
1429 1428 b'web', b'comparisoncontext', default=5,
1430 1429 )
1431 1430 coreconfigitem(
1432 1431 b'web', b'contact', default=None,
1433 1432 )
1434 1433 coreconfigitem(
1435 1434 b'web', b'deny_push', default=list,
1436 1435 )
1437 1436 coreconfigitem(
1438 1437 b'web', b'guessmime', default=False,
1439 1438 )
1440 1439 coreconfigitem(
1441 1440 b'web', b'hidden', default=False,
1442 1441 )
1443 1442 coreconfigitem(
1444 1443 b'web', b'labels', default=list,
1445 1444 )
1446 1445 coreconfigitem(
1447 1446 b'web', b'logoimg', default=b'hglogo.png',
1448 1447 )
1449 1448 coreconfigitem(
1450 1449 b'web', b'logourl', default=b'https://mercurial-scm.org/',
1451 1450 )
1452 1451 coreconfigitem(
1453 1452 b'web', b'accesslog', default=b'-',
1454 1453 )
1455 1454 coreconfigitem(
1456 1455 b'web', b'address', default=b'',
1457 1456 )
1458 1457 coreconfigitem(
1459 1458 b'web', b'allow-archive', alias=[(b'web', b'allow_archive')], default=list,
1460 1459 )
1461 1460 coreconfigitem(
1462 1461 b'web', b'allow_read', default=list,
1463 1462 )
1464 1463 coreconfigitem(
1465 1464 b'web', b'baseurl', default=None,
1466 1465 )
1467 1466 coreconfigitem(
1468 1467 b'web', b'cacerts', default=None,
1469 1468 )
1470 1469 coreconfigitem(
1471 1470 b'web', b'certificate', default=None,
1472 1471 )
1473 1472 coreconfigitem(
1474 1473 b'web', b'collapse', default=False,
1475 1474 )
1476 1475 coreconfigitem(
1477 1476 b'web', b'csp', default=None,
1478 1477 )
1479 1478 coreconfigitem(
1480 1479 b'web', b'deny_read', default=list,
1481 1480 )
1482 1481 coreconfigitem(
1483 1482 b'web', b'descend', default=True,
1484 1483 )
1485 1484 coreconfigitem(
1486 1485 b'web', b'description', default=b"",
1487 1486 )
1488 1487 coreconfigitem(
1489 1488 b'web', b'encoding', default=lambda: encoding.encoding,
1490 1489 )
1491 1490 coreconfigitem(
1492 1491 b'web', b'errorlog', default=b'-',
1493 1492 )
1494 1493 coreconfigitem(
1495 1494 b'web', b'ipv6', default=False,
1496 1495 )
1497 1496 coreconfigitem(
1498 1497 b'web', b'maxchanges', default=10,
1499 1498 )
1500 1499 coreconfigitem(
1501 1500 b'web', b'maxfiles', default=10,
1502 1501 )
1503 1502 coreconfigitem(
1504 1503 b'web', b'maxshortchanges', default=60,
1505 1504 )
1506 1505 coreconfigitem(
1507 1506 b'web', b'motd', default=b'',
1508 1507 )
1509 1508 coreconfigitem(
1510 1509 b'web', b'name', default=dynamicdefault,
1511 1510 )
1512 1511 coreconfigitem(
1513 1512 b'web', b'port', default=8000,
1514 1513 )
1515 1514 coreconfigitem(
1516 1515 b'web', b'prefix', default=b'',
1517 1516 )
1518 1517 coreconfigitem(
1519 1518 b'web', b'push_ssl', default=True,
1520 1519 )
1521 1520 coreconfigitem(
1522 1521 b'web', b'refreshinterval', default=20,
1523 1522 )
1524 1523 coreconfigitem(
1525 1524 b'web', b'server-header', default=None,
1526 1525 )
1527 1526 coreconfigitem(
1528 1527 b'web', b'static', default=None,
1529 1528 )
1530 1529 coreconfigitem(
1531 1530 b'web', b'staticurl', default=None,
1532 1531 )
1533 1532 coreconfigitem(
1534 1533 b'web', b'stripes', default=1,
1535 1534 )
1536 1535 coreconfigitem(
1537 1536 b'web', b'style', default=b'paper',
1538 1537 )
1539 1538 coreconfigitem(
1540 1539 b'web', b'templates', default=None,
1541 1540 )
1542 1541 coreconfigitem(
1543 1542 b'web', b'view', default=b'served', experimental=True,
1544 1543 )
1545 1544 coreconfigitem(
1546 1545 b'worker', b'backgroundclose', default=dynamicdefault,
1547 1546 )
1548 1547 # Windows defaults to a limit of 512 open files. A buffer of 128
1549 1548 # should give us enough headway.
1550 1549 coreconfigitem(
1551 1550 b'worker', b'backgroundclosemaxqueue', default=384,
1552 1551 )
1553 1552 coreconfigitem(
1554 1553 b'worker', b'backgroundcloseminfilecount', default=2048,
1555 1554 )
1556 1555 coreconfigitem(
1557 1556 b'worker', b'backgroundclosethreadcount', default=4,
1558 1557 )
1559 1558 coreconfigitem(
1560 1559 b'worker', b'enabled', default=True,
1561 1560 )
1562 1561 coreconfigitem(
1563 1562 b'worker', b'numcpus', default=None,
1564 1563 )
1565 1564
1566 1565 # Rebase related configuration moved to core because other extension are doing
1567 1566 # strange things. For example, shelve import the extensions to reuse some bit
1568 1567 # without formally loading it.
1569 1568 coreconfigitem(
1570 1569 b'commands', b'rebase.requiredest', default=False,
1571 1570 )
1572 1571 coreconfigitem(
1573 1572 b'experimental', b'rebaseskipobsolete', default=True,
1574 1573 )
1575 1574 coreconfigitem(
1576 1575 b'rebase', b'singletransaction', default=False,
1577 1576 )
1578 1577 coreconfigitem(
1579 1578 b'rebase', b'experimental.inmemory', default=False,
1580 1579 )
@@ -1,625 +1,628
1 1 # nodemap.py - nodemap related code and utilities
2 2 #
3 3 # Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 # Copyright 2019 George Racinet <georges.racinet@octobus.net>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import errno
12 12 import os
13 13 import re
14 14 import struct
15 15
16 16 from .. import (
17 17 error,
18 18 node as nodemod,
19 19 util,
20 20 )
21 21
22 22
23 23 class NodeMap(dict):
24 24 def __missing__(self, x):
25 25 raise error.RevlogError(b'unknown node: %s' % x)
26 26
27 27
28 28 def persisted_data(revlog):
29 29 """read the nodemap for a revlog from disk"""
30 30 if revlog.nodemap_file is None:
31 31 return None
32 32 pdata = revlog.opener.tryread(revlog.nodemap_file)
33 33 if not pdata:
34 34 return None
35 35 offset = 0
36 36 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size])
37 37 if version != ONDISK_VERSION:
38 38 return None
39 39 offset += S_VERSION.size
40 40 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
41 41 uid_size, tip_rev, data_length, data_unused, tip_node_size = headers
42 42 offset += S_HEADER.size
43 43 docket = NodeMapDocket(pdata[offset : offset + uid_size])
44 44 offset += uid_size
45 45 docket.tip_rev = tip_rev
46 46 docket.tip_node = pdata[offset : offset + tip_node_size]
47 47 docket.data_length = data_length
48 48 docket.data_unused = data_unused
49 49
50 50 filename = _rawdata_filepath(revlog, docket)
51 51 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap")
52 52 try:
53 53 with revlog.opener(filename) as fd:
54 54 if use_mmap:
55 55 data = util.buffer(util.mmapread(fd, data_length))
56 56 else:
57 57 data = fd.read(data_length)
58 58 except OSError as e:
59 59 if e.errno != errno.ENOENT:
60 60 raise
61 61 if len(data) < data_length:
62 62 return None
63 63 return docket, data
64 64
65 65
66 66 def setup_persistent_nodemap(tr, revlog):
67 67 """Install whatever is needed transaction side to persist a nodemap on disk
68 68
69 69 (only actually persist the nodemap if this is relevant for this revlog)
70 70 """
71 71 if revlog._inline:
72 72 return # inlined revlog are too small for this to be relevant
73 73 if revlog.nodemap_file is None:
74 74 return # we do not use persistent_nodemap on this revlog
75 75
76 76 # we need to happen after the changelog finalization, in that use "cl-"
77 77 callback_id = b"nm-revlog-persistent-nodemap-%s" % revlog.nodemap_file
78 78 if tr.hasfinalize(callback_id):
79 79 return # no need to register again
80 80 tr.addpending(
81 81 callback_id, lambda tr: _persist_nodemap(tr, revlog, pending=True)
82 82 )
83 83 tr.addfinalize(callback_id, lambda tr: _persist_nodemap(tr, revlog))
84 84
85 85
86 86 class _NoTransaction(object):
87 87 """transaction like object to update the nodemap outside a transaction
88 88 """
89 89
90 90 def __init__(self):
91 91 self._postclose = {}
92 92
93 93 def addpostclose(self, callback_id, callback_func):
94 94 self._postclose[callback_id] = callback_func
95 95
96 96 def registertmp(self, *args, **kwargs):
97 97 pass
98 98
99 99 def addbackup(self, *args, **kwargs):
100 100 pass
101 101
102 102 def add(self, *args, **kwargs):
103 103 pass
104 104
105 105 def addabort(self, *args, **kwargs):
106 106 pass
107 107
108 108
109 109 def update_persistent_nodemap(revlog):
110 110 """update the persistent nodemap right now
111 111
112 112 To be used for updating the nodemap on disk outside of a normal transaction
113 113 setup (eg, `debugupdatecache`).
114 114 """
115 115 notr = _NoTransaction()
116 116 _persist_nodemap(notr, revlog)
117 117 for k in sorted(notr._postclose):
118 118 notr._postclose[k](None)
119 119
120 120
121 121 def _persist_nodemap(tr, revlog, pending=False):
122 122 """Write nodemap data on disk for a given revlog
123 123 """
124 124 if getattr(revlog, 'filteredrevs', ()):
125 125 raise error.ProgrammingError(
126 126 "cannot persist nodemap of a filtered changelog"
127 127 )
128 128 if revlog.nodemap_file is None:
129 129 msg = "calling persist nodemap on a revlog without the feature enableb"
130 130 raise error.ProgrammingError(msg)
131 131
132 132 can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental")
133 133 ondisk_docket = revlog._nodemap_docket
134 134 feed_data = util.safehasattr(revlog.index, "update_nodemap_data")
135 135 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap")
136 136
137 137 data = None
138 138 # first attemp an incremental update of the data
139 139 if can_incremental and ondisk_docket is not None:
140 140 target_docket = revlog._nodemap_docket.copy()
141 141 (
142 142 src_docket,
143 143 data_changed_count,
144 144 data,
145 145 ) = revlog.index.nodemap_data_incremental()
146 new_length = target_docket.data_length + len(data)
147 new_unused = target_docket.data_unused + data_changed_count
146 148 if src_docket != target_docket:
147 149 data = None
150 elif new_length <= (new_unused * 10): # under 10% of unused data
151 data = None
148 152 else:
149 153 datafile = _rawdata_filepath(revlog, target_docket)
150 154 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
151 155 # store vfs
152 new_length = target_docket.data_length + len(data)
153 156 tr.add(datafile, target_docket.data_length)
154 157 with revlog.opener(datafile, b'r+') as fd:
155 158 fd.seek(target_docket.data_length)
156 159 fd.write(data)
157 160 if feed_data:
158 161 if use_mmap:
159 162 fd.seek(0)
160 163 new_data = fd.read(new_length)
161 164 else:
162 165 fd.flush()
163 166 new_data = util.buffer(util.mmapread(fd, new_length))
164 167 target_docket.data_length = new_length
165 target_docket.data_unused += data_changed_count
168 target_docket.data_unused = new_unused
166 169
167 170 if data is None:
168 171 # otherwise fallback to a full new export
169 172 target_docket = NodeMapDocket()
170 173 datafile = _rawdata_filepath(revlog, target_docket)
171 174 if util.safehasattr(revlog.index, "nodemap_data_all"):
172 175 data = revlog.index.nodemap_data_all()
173 176 else:
174 177 data = persistent_data(revlog.index)
175 178 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
176 179 # store vfs
177 180
178 181 tryunlink = revlog.opener.tryunlink
179 182
180 183 def abortck(tr):
181 184 tryunlink(datafile)
182 185
183 186 callback_id = b"delete-%s" % datafile
184 187
185 188 # some flavor of the transaction abort does not cleanup new file, it
186 189 # simply empty them.
187 190 tr.addabort(callback_id, abortck)
188 191 with revlog.opener(datafile, b'w+') as fd:
189 192 fd.write(data)
190 193 if feed_data:
191 194 if use_mmap:
192 195 new_data = data
193 196 else:
194 197 fd.flush()
195 198 new_data = util.buffer(util.mmapread(fd, len(data)))
196 199 target_docket.data_length = len(data)
197 200 target_docket.tip_rev = revlog.tiprev()
198 201 target_docket.tip_node = revlog.node(target_docket.tip_rev)
199 202 # EXP-TODO: if this is a cache, this should use a cache vfs, not a
200 203 # store vfs
201 204 file_path = revlog.nodemap_file
202 205 if pending:
203 206 file_path += b'.a'
204 207 tr.registertmp(file_path)
205 208 else:
206 209 tr.addbackup(file_path)
207 210
208 211 with revlog.opener(file_path, b'w', atomictemp=True) as fp:
209 212 fp.write(target_docket.serialize())
210 213 revlog._nodemap_docket = target_docket
211 214 if feed_data:
212 215 revlog.index.update_nodemap_data(target_docket, new_data)
213 216
214 217 # search for old index file in all cases, some older process might have
215 218 # left one behind.
216 219 olds = _other_rawdata_filepath(revlog, target_docket)
217 220 if olds:
218 221 realvfs = getattr(revlog, '_realopener', revlog.opener)
219 222
220 223 def cleanup(tr):
221 224 for oldfile in olds:
222 225 realvfs.tryunlink(oldfile)
223 226
224 227 callback_id = b"revlog-cleanup-nodemap-%s" % revlog.nodemap_file
225 228 tr.addpostclose(callback_id, cleanup)
226 229
227 230
228 231 ### Nodemap docket file
229 232 #
230 233 # The nodemap data are stored on disk using 2 files:
231 234 #
232 235 # * a raw data files containing a persistent nodemap
233 236 # (see `Nodemap Trie` section)
234 237 #
235 238 # * a small "docket" file containing medatadata
236 239 #
237 240 # While the nodemap data can be multiple tens of megabytes, the "docket" is
238 241 # small, it is easy to update it automatically or to duplicated its content
239 242 # during a transaction.
240 243 #
241 244 # Multiple raw data can exist at the same time (The currently valid one and a
242 245 # new one beind used by an in progress transaction). To accomodate this, the
243 246 # filename hosting the raw data has a variable parts. The exact filename is
244 247 # specified inside the "docket" file.
245 248 #
246 249 # The docket file contains information to find, qualify and validate the raw
247 250 # data. Its content is currently very light, but it will expand as the on disk
248 251 # nodemap gains the necessary features to be used in production.
249 252
250 253 # version 0 is experimental, no BC garantee, do no use outside of tests.
251 254 ONDISK_VERSION = 0
252 255 S_VERSION = struct.Struct(">B")
253 256 S_HEADER = struct.Struct(">BQQQQ")
254 257
255 258 ID_SIZE = 8
256 259
257 260
258 261 def _make_uid():
259 262 """return a new unique identifier.
260 263
261 264 The identifier is random and composed of ascii characters."""
262 265 return nodemod.hex(os.urandom(ID_SIZE))
263 266
264 267
265 268 class NodeMapDocket(object):
266 269 """metadata associated with persistent nodemap data
267 270
268 271 The persistent data may come from disk or be on their way to disk.
269 272 """
270 273
271 274 def __init__(self, uid=None):
272 275 if uid is None:
273 276 uid = _make_uid()
274 277 # a unique identifier for the data file:
275 278 # - When new data are appended, it is preserved.
276 279 # - When a new data file is created, a new identifier is generated.
277 280 self.uid = uid
278 281 # the tipmost revision stored in the data file. This revision and all
279 282 # revision before it are expected to be encoded in the data file.
280 283 self.tip_rev = None
281 284 # the node of that tipmost revision, if it mismatch the current index
282 285 # data the docket is not valid for the current index and should be
283 286 # discarded.
284 287 #
285 288 # note: this method is not perfect as some destructive operation could
286 289 # preserve the same tip_rev + tip_node while altering lower revision.
287 290 # However this multiple other caches have the same vulnerability (eg:
288 291 # brancmap cache).
289 292 self.tip_node = None
290 293 # the size (in bytes) of the persisted data to encode the nodemap valid
291 294 # for `tip_rev`.
292 295 # - data file shorter than this are corrupted,
293 296 # - any extra data should be ignored.
294 297 self.data_length = None
295 298 # the amount (in bytes) of "dead" data, still in the data file but no
296 299 # longer used for the nodemap.
297 300 self.data_unused = 0
298 301
299 302 def copy(self):
300 303 new = NodeMapDocket(uid=self.uid)
301 304 new.tip_rev = self.tip_rev
302 305 new.tip_node = self.tip_node
303 306 new.data_length = self.data_length
304 307 new.data_unused = self.data_unused
305 308 return new
306 309
307 310 def __cmp__(self, other):
308 311 if self.uid < other.uid:
309 312 return -1
310 313 if self.uid > other.uid:
311 314 return 1
312 315 elif self.data_length < other.data_length:
313 316 return -1
314 317 elif self.data_length > other.data_length:
315 318 return 1
316 319 return 0
317 320
318 321 def __eq__(self, other):
319 322 return self.uid == other.uid and self.data_length == other.data_length
320 323
321 324 def serialize(self):
322 325 """return serialized bytes for a docket using the passed uid"""
323 326 data = []
324 327 data.append(S_VERSION.pack(ONDISK_VERSION))
325 328 headers = (
326 329 len(self.uid),
327 330 self.tip_rev,
328 331 self.data_length,
329 332 self.data_unused,
330 333 len(self.tip_node),
331 334 )
332 335 data.append(S_HEADER.pack(*headers))
333 336 data.append(self.uid)
334 337 data.append(self.tip_node)
335 338 return b''.join(data)
336 339
337 340
338 341 def _rawdata_filepath(revlog, docket):
339 342 """The (vfs relative) nodemap's rawdata file for a given uid"""
340 343 if revlog.nodemap_file.endswith(b'.n.a'):
341 344 prefix = revlog.nodemap_file[:-4]
342 345 else:
343 346 prefix = revlog.nodemap_file[:-2]
344 347 return b"%s-%s.nd" % (prefix, docket.uid)
345 348
346 349
347 350 def _other_rawdata_filepath(revlog, docket):
348 351 prefix = revlog.nodemap_file[:-2]
349 352 pattern = re.compile(br"(^|/)%s-[0-9a-f]+\.nd$" % prefix)
350 353 new_file_path = _rawdata_filepath(revlog, docket)
351 354 new_file_name = revlog.opener.basename(new_file_path)
352 355 dirpath = revlog.opener.dirname(new_file_path)
353 356 others = []
354 357 for f in revlog.opener.listdir(dirpath):
355 358 if pattern.match(f) and f != new_file_name:
356 359 others.append(f)
357 360 return others
358 361
359 362
360 363 ### Nodemap Trie
361 364 #
362 365 # This is a simple reference implementation to compute and persist a nodemap
363 366 # trie. This reference implementation is write only. The python version of this
364 367 # is not expected to be actually used, since it wont provide performance
365 368 # improvement over existing non-persistent C implementation.
366 369 #
367 370 # The nodemap is persisted as Trie using 4bits-address/16-entries block. each
368 371 # revision can be adressed using its node shortest prefix.
369 372 #
370 373 # The trie is stored as a sequence of block. Each block contains 16 entries
371 374 # (signed 64bit integer, big endian). Each entry can be one of the following:
372 375 #
373 376 # * value >= 0 -> index of sub-block
374 377 # * value == -1 -> no value
375 378 # * value < -1 -> a revision value: rev = -(value+10)
376 379 #
377 380 # The implementation focus on simplicity, not on performance. A Rust
378 381 # implementation should provide a efficient version of the same binary
379 382 # persistence. This reference python implementation is never meant to be
380 383 # extensively use in production.
381 384
382 385
383 386 def persistent_data(index):
384 387 """return the persistent binary form for a nodemap for a given index
385 388 """
386 389 trie = _build_trie(index)
387 390 return _persist_trie(trie)
388 391
389 392
390 393 def update_persistent_data(index, root, max_idx, last_rev):
391 394 """return the incremental update for persistent nodemap from a given index
392 395 """
393 396 changed_block, trie = _update_trie(index, root, last_rev)
394 397 return (
395 398 changed_block * S_BLOCK.size,
396 399 _persist_trie(trie, existing_idx=max_idx),
397 400 )
398 401
399 402
400 403 S_BLOCK = struct.Struct(">" + ("l" * 16))
401 404
402 405 NO_ENTRY = -1
403 406 # rev 0 need to be -2 because 0 is used by block, -1 is a special value.
404 407 REV_OFFSET = 2
405 408
406 409
407 410 def _transform_rev(rev):
408 411 """Return the number used to represent the rev in the tree.
409 412
410 413 (or retrieve a rev number from such representation)
411 414
412 415 Note that this is an involution, a function equal to its inverse (i.e.
413 416 which gives the identity when applied to itself).
414 417 """
415 418 return -(rev + REV_OFFSET)
416 419
417 420
418 421 def _to_int(hex_digit):
419 422 """turn an hexadecimal digit into a proper integer"""
420 423 return int(hex_digit, 16)
421 424
422 425
423 426 class Block(dict):
424 427 """represent a block of the Trie
425 428
426 429 contains up to 16 entry indexed from 0 to 15"""
427 430
428 431 def __init__(self):
429 432 super(Block, self).__init__()
430 433 # If this block exist on disk, here is its ID
431 434 self.ondisk_id = None
432 435
433 436 def __iter__(self):
434 437 return iter(self.get(i) for i in range(16))
435 438
436 439
437 440 def _build_trie(index):
438 441 """build a nodemap trie
439 442
440 443 The nodemap stores revision number for each unique prefix.
441 444
442 445 Each block is a dictionary with keys in `[0, 15]`. Values are either
443 446 another block or a revision number.
444 447 """
445 448 root = Block()
446 449 for rev in range(len(index)):
447 450 hex = nodemod.hex(index[rev][7])
448 451 _insert_into_block(index, 0, root, rev, hex)
449 452 return root
450 453
451 454
452 455 def _update_trie(index, root, last_rev):
453 456 """consume"""
454 457 changed = 0
455 458 for rev in range(last_rev + 1, len(index)):
456 459 hex = nodemod.hex(index[rev][7])
457 460 changed += _insert_into_block(index, 0, root, rev, hex)
458 461 return changed, root
459 462
460 463
461 464 def _insert_into_block(index, level, block, current_rev, current_hex):
462 465 """insert a new revision in a block
463 466
464 467 index: the index we are adding revision for
465 468 level: the depth of the current block in the trie
466 469 block: the block currently being considered
467 470 current_rev: the revision number we are adding
468 471 current_hex: the hexadecimal representation of the of that revision
469 472 """
470 473 changed = 1
471 474 if block.ondisk_id is not None:
472 475 block.ondisk_id = None
473 476 hex_digit = _to_int(current_hex[level : level + 1])
474 477 entry = block.get(hex_digit)
475 478 if entry is None:
476 479 # no entry, simply store the revision number
477 480 block[hex_digit] = current_rev
478 481 elif isinstance(entry, dict):
479 482 # need to recurse to an underlying block
480 483 changed += _insert_into_block(
481 484 index, level + 1, entry, current_rev, current_hex
482 485 )
483 486 else:
484 487 # collision with a previously unique prefix, inserting new
485 488 # vertices to fit both entry.
486 489 other_hex = nodemod.hex(index[entry][7])
487 490 other_rev = entry
488 491 new = Block()
489 492 block[hex_digit] = new
490 493 _insert_into_block(index, level + 1, new, other_rev, other_hex)
491 494 _insert_into_block(index, level + 1, new, current_rev, current_hex)
492 495 return changed
493 496
494 497
495 498 def _persist_trie(root, existing_idx=None):
496 499 """turn a nodemap trie into persistent binary data
497 500
498 501 See `_build_trie` for nodemap trie structure"""
499 502 block_map = {}
500 503 if existing_idx is not None:
501 504 base_idx = existing_idx + 1
502 505 else:
503 506 base_idx = 0
504 507 chunks = []
505 508 for tn in _walk_trie(root):
506 509 if tn.ondisk_id is not None:
507 510 block_map[id(tn)] = tn.ondisk_id
508 511 else:
509 512 block_map[id(tn)] = len(chunks) + base_idx
510 513 chunks.append(_persist_block(tn, block_map))
511 514 return b''.join(chunks)
512 515
513 516
514 517 def _walk_trie(block):
515 518 """yield all the block in a trie
516 519
517 520 Children blocks are always yield before their parent block.
518 521 """
519 522 for (_, item) in sorted(block.items()):
520 523 if isinstance(item, dict):
521 524 for sub_block in _walk_trie(item):
522 525 yield sub_block
523 526 yield block
524 527
525 528
526 529 def _persist_block(block_node, block_map):
527 530 """produce persistent binary data for a single block
528 531
529 532 Children block are assumed to be already persisted and present in
530 533 block_map.
531 534 """
532 535 data = tuple(_to_value(v, block_map) for v in block_node)
533 536 return S_BLOCK.pack(*data)
534 537
535 538
536 539 def _to_value(item, block_map):
537 540 """persist any value as an integer"""
538 541 if item is None:
539 542 return NO_ENTRY
540 543 elif isinstance(item, dict):
541 544 return block_map[id(item)]
542 545 else:
543 546 return _transform_rev(item)
544 547
545 548
546 549 def parse_data(data):
547 550 """parse parse nodemap data into a nodemap Trie"""
548 551 if (len(data) % S_BLOCK.size) != 0:
549 552 msg = "nodemap data size is not a multiple of block size (%d): %d"
550 553 raise error.Abort(msg % (S_BLOCK.size, len(data)))
551 554 if not data:
552 555 return Block(), None
553 556 block_map = {}
554 557 new_blocks = []
555 558 for i in range(0, len(data), S_BLOCK.size):
556 559 block = Block()
557 560 block.ondisk_id = len(block_map)
558 561 block_map[block.ondisk_id] = block
559 562 block_data = data[i : i + S_BLOCK.size]
560 563 values = S_BLOCK.unpack(block_data)
561 564 new_blocks.append((block, values))
562 565 for b, values in new_blocks:
563 566 for idx, v in enumerate(values):
564 567 if v == NO_ENTRY:
565 568 continue
566 569 elif v >= 0:
567 570 b[idx] = block_map[v]
568 571 else:
569 572 b[idx] = _transform_rev(v)
570 573 return block, i // S_BLOCK.size
571 574
572 575
573 576 # debug utility
574 577
575 578
576 579 def check_data(ui, index, data):
577 580 """verify that the provided nodemap data are valid for the given idex"""
578 581 ret = 0
579 582 ui.status((b"revision in index: %d\n") % len(index))
580 583 root, __ = parse_data(data)
581 584 all_revs = set(_all_revisions(root))
582 585 ui.status((b"revision in nodemap: %d\n") % len(all_revs))
583 586 for r in range(len(index)):
584 587 if r not in all_revs:
585 588 msg = b" revision missing from nodemap: %d\n" % r
586 589 ui.write_err(msg)
587 590 ret = 1
588 591 else:
589 592 all_revs.remove(r)
590 593 nm_rev = _find_node(root, nodemod.hex(index[r][7]))
591 594 if nm_rev is None:
592 595 msg = b" revision node does not match any entries: %d\n" % r
593 596 ui.write_err(msg)
594 597 ret = 1
595 598 elif nm_rev != r:
596 599 msg = (
597 600 b" revision node does not match the expected revision: "
598 601 b"%d != %d\n" % (r, nm_rev)
599 602 )
600 603 ui.write_err(msg)
601 604 ret = 1
602 605
603 606 if all_revs:
604 607 for r in sorted(all_revs):
605 608 msg = b" extra revision in nodemap: %d\n" % r
606 609 ui.write_err(msg)
607 610 ret = 1
608 611 return ret
609 612
610 613
611 614 def _all_revisions(root):
612 615 """return all revisions stored in a Trie"""
613 616 for block in _walk_trie(root):
614 617 for v in block:
615 618 if v is None or isinstance(v, Block):
616 619 continue
617 620 yield v
618 621
619 622
620 623 def _find_node(block, node):
621 624 """find the revision associated with a given node"""
622 625 entry = block.get(_to_int(node[0:1]))
623 626 if isinstance(entry, dict):
624 627 return _find_node(entry, node[1:])
625 628 return entry
@@ -1,413 +1,413
1 1 ===================================
2 2 Test the persistent on-disk nodemap
3 3 ===================================
4 4
5 5 $ hg init test-repo
6 6 $ cd test-repo
7 7 $ cat << EOF >> .hg/hgrc
8 8 > [experimental]
9 9 > exp-persistent-nodemap=yes
10 10 > [devel]
11 11 > persistent-nodemap=yes
12 12 > EOF
13 13 $ hg debugbuilddag .+5000
14 14 $ hg debugnodemap --metadata
15 15 uid: ???????????????? (glob)
16 16 tip-rev: 5000
17 17 tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
18 18 data-length: 122880
19 19 data-unused: 0
20 20 data-unused: 0.000%
21 21 $ f --size .hg/store/00changelog.n
22 22 .hg/store/00changelog.n: size=70
23 23
24 24 Simple lookup works
25 25
26 26 $ ANYNODE=`hg log --template '{node|short}\n' --rev tip`
27 27 $ hg log -r "$ANYNODE" --template '{rev}\n'
28 28 5000
29 29
30 30
31 31 #if rust
32 32
33 33 $ f --sha256 .hg/store/00changelog-*.nd
34 34 .hg/store/00changelog-????????????????.nd: sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6 (glob)
35 35 $ hg debugnodemap --dump-new | f --sha256 --size
36 36 size=122880, sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6
37 37 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
38 38 size=122880, sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6
39 39 0000: 00 00 00 76 00 00 01 65 00 00 00 95 00 00 01 34 |...v...e.......4|
40 40 0010: 00 00 00 19 00 00 01 69 00 00 00 ab 00 00 00 4b |.......i.......K|
41 41 0020: 00 00 00 07 00 00 01 4c 00 00 00 f8 00 00 00 8f |.......L........|
42 42 0030: 00 00 00 c0 00 00 00 a7 00 00 00 89 00 00 01 46 |...............F|
43 43 0040: 00 00 00 92 00 00 01 bc 00 00 00 71 00 00 00 ac |...........q....|
44 44 0050: 00 00 00 af 00 00 00 b4 00 00 00 34 00 00 01 ca |...........4....|
45 45 0060: 00 00 00 23 00 00 01 45 00 00 00 2d 00 00 00 b2 |...#...E...-....|
46 46 0070: 00 00 00 56 00 00 01 0f 00 00 00 4e 00 00 02 4c |...V.......N...L|
47 47 0080: 00 00 00 e7 00 00 00 cd 00 00 01 5b 00 00 00 78 |...........[...x|
48 48 0090: 00 00 00 e3 00 00 01 8e 00 00 00 4f 00 00 00 b1 |...........O....|
49 49 00a0: 00 00 00 30 00 00 00 11 00 00 00 25 00 00 00 d2 |...0.......%....|
50 50 00b0: 00 00 00 ec 00 00 00 69 00 00 01 2b 00 00 01 2e |.......i...+....|
51 51 00c0: 00 00 00 aa 00 00 00 15 00 00 00 3a 00 00 01 4e |...........:...N|
52 52 00d0: 00 00 00 4d 00 00 00 9d 00 00 00 8e 00 00 00 a4 |...M............|
53 53 00e0: 00 00 00 c3 00 00 00 eb 00 00 00 29 00 00 00 ad |...........)....|
54 54 00f0: 00 00 01 3a 00 00 01 32 00 00 00 04 00 00 00 53 |...:...2.......S|
55 55
56 56
57 57 #else
58 58
59 59 $ f --sha256 .hg/store/00changelog-*.nd
60 60 .hg/store/00changelog-????????????????.nd: sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7 (glob)
61 61 $ hg debugnodemap --dump-new | f --sha256 --size
62 62 size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
63 63 $ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
64 64 size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
65 65 0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
66 66 0010: ff ff ff ff ff ff ff ff ff ff fa c2 ff ff ff ff |................|
67 67 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
68 68 0030: ff ff ff ff ff ff ed b3 ff ff ff ff ff ff ff ff |................|
69 69 0040: ff ff ff ff ff ff ee 34 00 00 00 00 ff ff ff ff |.......4........|
70 70 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
71 71 0060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
72 72 0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
73 73 0080: ff ff ff ff ff ff f8 50 ff ff ff ff ff ff ff ff |.......P........|
74 74 0090: ff ff ff ff ff ff ff ff ff ff ec c7 ff ff ff ff |................|
75 75 00a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
76 76 00b0: ff ff ff ff ff ff fa be ff ff f2 fc ff ff ff ff |................|
77 77 00c0: ff ff ff ff ff ff ef ea ff ff ff ff ff ff f9 17 |................|
78 78 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
79 79 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
80 80 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
81 81
82 82 #endif
83 83
84 84 $ hg debugnodemap --check
85 85 revision in index: 5001
86 86 revision in nodemap: 5001
87 87
88 88 add a new commit
89 89
90 90 $ hg up
91 91 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 92 $ echo foo > foo
93 93 $ hg add foo
94 94 $ hg ci -m 'foo'
95 95
96 96 #if no-pure no-rust
97 97 $ hg debugnodemap --metadata
98 98 uid: ???????????????? (glob)
99 99 tip-rev: 5001
100 100 tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
101 101 data-length: 122880
102 102 data-unused: 0
103 103 data-unused: 0.000%
104 104 #else
105 105 $ hg debugnodemap --metadata
106 106 uid: ???????????????? (glob)
107 107 tip-rev: 5001
108 108 tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
109 109 data-length: 123072
110 110 data-unused: 192
111 111 data-unused: 0.156%
112 112 #endif
113 113
114 114 $ f --size .hg/store/00changelog.n
115 115 .hg/store/00changelog.n: size=70
116 116
117 117 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)
118 118
119 119 #if pure
120 120 $ f --sha256 .hg/store/00changelog-*.nd --size
121 121 .hg/store/00changelog-????????????????.nd: size=123072, sha256=136472751566c8198ff09e306a7d2f9bd18bd32298d614752b73da4d6df23340 (glob)
122 122 #endif
123 123
124 124 #if rust
125 125 $ f --sha256 .hg/store/00changelog-*.nd --size
126 126 .hg/store/00changelog-????????????????.nd: size=123072, sha256=ccc8a43310ace13812fcc648683e259346754ef934c12dd238cf9b7fadfe9a4b (glob)
127 127 #endif
128 128
129 129 #if no-pure no-rust
130 130 $ f --sha256 .hg/store/00changelog-*.nd --size
131 131 .hg/store/00changelog-????????????????.nd: size=122880, sha256=bfafebd751c4f6d116a76a37a1dee2a251747affe7efbcc4f4842ccc746d4db9 (glob)
132 132 #endif
133 133
134 134 $ hg debugnodemap --check
135 135 revision in index: 5002
136 136 revision in nodemap: 5002
137 137
138 138 Test code path without mmap
139 139 ---------------------------
140 140
141 141 $ echo bar > bar
142 142 $ hg add bar
143 143 $ hg ci -m 'bar' --config experimental.exp-persistent-nodemap.mmap=no
144 144
145 145 $ hg debugnodemap --check --config experimental.exp-persistent-nodemap.mmap=yes
146 146 revision in index: 5003
147 147 revision in nodemap: 5003
148 148 $ hg debugnodemap --check --config experimental.exp-persistent-nodemap.mmap=no
149 149 revision in index: 5003
150 150 revision in nodemap: 5003
151 151
152 152
153 153 #if pure
154 154 $ hg debugnodemap --metadata
155 155 uid: ???????????????? (glob)
156 156 tip-rev: 5002
157 157 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
158 158 data-length: 123328
159 159 data-unused: 384
160 160 data-unused: 0.311%
161 161 $ f --sha256 .hg/store/00changelog-*.nd --size
162 162 .hg/store/00changelog-????????????????.nd: size=123328, sha256=10d26e9776b6596af0f89143a54eba8cc581e929c38242a02a7b0760698c6c70 (glob)
163 163 #endif
164 164 #if rust
165 165 $ hg debugnodemap --metadata
166 166 uid: ???????????????? (glob)
167 167 tip-rev: 5002
168 168 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
169 169 data-length: 123328
170 170 data-unused: 384
171 171 data-unused: 0.311%
172 172 $ f --sha256 .hg/store/00changelog-*.nd --size
173 173 .hg/store/00changelog-????????????????.nd: size=123328, sha256=081eec9eb6708f2bf085d939b4c97bc0b6762bc8336bc4b93838f7fffa1516bf (glob)
174 174 #endif
175 175 #if no-pure no-rust
176 176 $ hg debugnodemap --metadata
177 177 uid: ???????????????? (glob)
178 178 tip-rev: 5002
179 179 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
180 180 data-length: 122944
181 181 data-unused: 0
182 182 data-unused: 0.000%
183 183 $ f --sha256 .hg/store/00changelog-*.nd --size
184 184 .hg/store/00changelog-????????????????.nd: size=122944, sha256=755976b22b64ab680401b45395953504e64e7fa8c31ac570f58dee21e15f9bc0 (glob)
185 185 #endif
186 186
187 187 Test force warming the cache
188 188
189 189 $ rm .hg/store/00changelog.n
190 190 $ hg debugnodemap --metadata
191 191 $ hg debugupdatecache
192 192 #if pure
193 193 $ hg debugnodemap --metadata
194 194 uid: ???????????????? (glob)
195 195 tip-rev: 5002
196 196 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
197 197 data-length: 122944
198 198 data-unused: 0
199 199 data-unused: 0.000%
200 200 #else
201 201 $ hg debugnodemap --metadata
202 202 uid: ???????????????? (glob)
203 203 tip-rev: 5002
204 204 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
205 205 data-length: 122944
206 206 data-unused: 0
207 207 data-unused: 0.000%
208 208 #endif
209 209
210 210 Check out of sync nodemap
211 211 =========================
212 212
213 213 First copy old data on the side.
214 214
215 215 $ mkdir ../tmp-copies
216 216 $ cp .hg/store/00changelog-????????????????.nd .hg/store/00changelog.n ../tmp-copies
217 217
218 218 Nodemap lagging behind
219 219 ----------------------
220 220
221 221 make a new commit
222 222
223 223 $ echo bar2 > bar
224 224 $ hg ci -m 'bar2'
225 225 $ NODE=`hg log -r tip -T '{node}\n'`
226 226 $ hg log -r "$NODE" -T '{rev}\n'
227 227 5003
228 228
229 229 If the nodemap is lagging behind, it can catch up fine
230 230
231 231 $ hg debugnodemap --metadata
232 232 uid: ???????????????? (glob)
233 233 tip-rev: 5003
234 234 tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
235 235 data-length: 123200 (pure !)
236 236 data-length: 123200 (rust !)
237 237 data-length: 122944 (no-rust no-pure !)
238 238 data-unused: 256 (pure !)
239 239 data-unused: 256 (rust !)
240 240 data-unused: 0 (no-rust no-pure !)
241 241 data-unused: 0.208% (pure !)
242 242 data-unused: 0.208% (rust !)
243 243 data-unused: 0.000% (no-rust no-pure !)
244 244 $ cp -f ../tmp-copies/* .hg/store/
245 245 $ hg debugnodemap --metadata
246 246 uid: ???????????????? (glob)
247 247 tip-rev: 5002
248 248 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
249 249 data-length: 122944
250 250 data-unused: 0
251 251 data-unused: 0.000%
252 252 $ hg log -r "$NODE" -T '{rev}\n'
253 253 5003
254 254
255 255 changelog altered
256 256 -----------------
257 257
258 258 If the nodemap is not gated behind a requirements, an unaware client can alter
259 259 the repository so the revlog used to generate the nodemap is not longer
260 260 compatible with the persistent nodemap. We need to detect that.
261 261
262 262 $ hg up "$NODE~5"
263 263 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
264 264 $ echo bar > babar
265 265 $ hg add babar
266 266 $ hg ci -m 'babar'
267 267 created new head
268 268 $ OTHERNODE=`hg log -r tip -T '{node}\n'`
269 269 $ hg log -r "$OTHERNODE" -T '{rev}\n'
270 270 5004
271 271
272 272 $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
273 273
274 274 the nodemap should detect the changelog have been tampered with and recover.
275 275
276 276 $ hg debugnodemap --metadata
277 277 uid: ???????????????? (glob)
278 278 tip-rev: 5002
279 279 tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
280 280 data-length: 123456 (pure !)
281 data-length: 246464 (rust !)
281 data-length: 123008 (rust !)
282 282 data-length: 123008 (no-pure no-rust !)
283 283 data-unused: 448 (pure !)
284 data-unused: 123904 (rust !)
284 data-unused: 0 (rust !)
285 285 data-unused: 0 (no-pure no-rust !)
286 data-unused: 50.273% (rust !)
286 data-unused: 0.000% (rust !)
287 287 data-unused: 0.363% (pure !)
288 288 data-unused: 0.000% (no-pure no-rust !)
289 289
290 290 $ cp -f ../tmp-copies/* .hg/store/
291 291 $ hg debugnodemap --metadata
292 292 uid: ???????????????? (glob)
293 293 tip-rev: 5002
294 294 tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
295 295 data-length: 122944
296 296 data-unused: 0
297 297 data-unused: 0.000%
298 298 $ hg log -r "$OTHERNODE" -T '{rev}\n'
299 299 5002
300 300
301 301 Check transaction related property
302 302 ==================================
303 303
304 304 An up to date nodemap should be available to shell hooks,
305 305
306 306 $ echo dsljfl > a
307 307 $ hg add a
308 308 $ hg ci -m a
309 309 $ hg debugnodemap --metadata
310 310 uid: ???????????????? (glob)
311 311 tip-rev: 5003
312 312 tip-node: c91af76d172f1053cca41b83f7c2e4e514fe2bcf
313 313 data-length: 123008
314 314 data-unused: 0
315 315 data-unused: 0.000%
316 316 $ echo babar2 > babar
317 317 $ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
318 318 uid: ???????????????? (glob)
319 319 tip-rev: 5004
320 320 tip-node: ba87cd9559559e4b91b28cb140d003985315e031
321 321 data-length: 123328 (pure !)
322 322 data-length: 123328 (rust !)
323 323 data-length: 123136 (no-pure no-rust !)
324 324 data-unused: 192 (pure !)
325 325 data-unused: 192 (rust !)
326 326 data-unused: 0 (no-pure no-rust !)
327 327 data-unused: 0.156% (pure !)
328 328 data-unused: 0.156% (rust !)
329 329 data-unused: 0.000% (no-pure no-rust !)
330 330 $ hg debugnodemap --metadata
331 331 uid: ???????????????? (glob)
332 332 tip-rev: 5004
333 333 tip-node: ba87cd9559559e4b91b28cb140d003985315e031
334 334 data-length: 123328 (pure !)
335 335 data-length: 123328 (rust !)
336 336 data-length: 123136 (no-pure no-rust !)
337 337 data-unused: 192 (pure !)
338 338 data-unused: 192 (rust !)
339 339 data-unused: 0 (no-pure no-rust !)
340 340 data-unused: 0.156% (pure !)
341 341 data-unused: 0.156% (rust !)
342 342 data-unused: 0.000% (no-pure no-rust !)
343 343
344 344 Another process does not see the pending nodemap content during run.
345 345
346 346 $ PATH=$RUNTESTDIR/testlib/:$PATH
347 347 $ echo qpoasp > a
348 348 $ hg ci -m a2 \
349 349 > --config "hooks.pretxnclose=wait-on-file 20 sync-repo-read sync-txn-pending" \
350 350 > --config "hooks.txnclose=touch sync-txn-close" > output.txt 2>&1 &
351 351
352 352 (read the repository while the commit transaction is pending)
353 353
354 354 $ wait-on-file 20 sync-txn-pending && \
355 355 > hg debugnodemap --metadata && \
356 356 > wait-on-file 20 sync-txn-close sync-repo-read
357 357 uid: ???????????????? (glob)
358 358 tip-rev: 5004
359 359 tip-node: ba87cd9559559e4b91b28cb140d003985315e031
360 360 data-length: 123328 (pure !)
361 361 data-length: 123328 (rust !)
362 362 data-length: 123136 (no-pure no-rust !)
363 363 data-unused: 192 (pure !)
364 364 data-unused: 192 (rust !)
365 365 data-unused: 0 (no-pure no-rust !)
366 366 data-unused: 0.156% (pure !)
367 367 data-unused: 0.156% (rust !)
368 368 data-unused: 0.000% (no-pure no-rust !)
369 369 $ hg debugnodemap --metadata
370 370 uid: ???????????????? (glob)
371 371 tip-rev: 5005
372 372 tip-node: bae4d45c759e30f1cb1a40e1382cf0e0414154db
373 373 data-length: 123584 (pure !)
374 374 data-length: 123584 (rust !)
375 375 data-length: 123136 (no-pure no-rust !)
376 376 data-unused: 448 (pure !)
377 377 data-unused: 448 (rust !)
378 378 data-unused: 0 (no-pure no-rust !)
379 379 data-unused: 0.363% (pure !)
380 380 data-unused: 0.363% (rust !)
381 381 data-unused: 0.000% (no-pure no-rust !)
382 382
383 383 $ cat output.txt
384 384
385 385 Check that a failing transaction will properly revert the data
386 386
387 387 $ echo plakfe > a
388 388 $ f --size --sha256 .hg/store/00changelog-*.nd
389 389 .hg/store/00changelog-????????????????.nd: size=123584, sha256=8c6cef6fd3d3fac291968793ee19a4be6d0b8375e9508bd5c7d4a8879e8df180 (glob) (pure !)
390 390 .hg/store/00changelog-????????????????.nd: size=123584, sha256=eb9e9a4bcafdb5e1344bc8a0cbb3288b2106413b8efae6265fb8a7973d7e97f9 (glob) (rust !)
391 391 .hg/store/00changelog-????????????????.nd: size=123136, sha256=4f504f5a834db3811ced50ab3e9e80bcae3581bb0f9b13a7a9f94b7fc34bcebe (glob) (no-pure no-rust !)
392 392 $ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
393 393 transaction abort!
394 394 rollback completed
395 395 abort: This is a late abort
396 396 [255]
397 397 $ hg debugnodemap --metadata
398 398 uid: ???????????????? (glob)
399 399 tip-rev: 5005
400 400 tip-node: bae4d45c759e30f1cb1a40e1382cf0e0414154db
401 401 data-length: 123584 (pure !)
402 402 data-length: 123584 (rust !)
403 403 data-length: 123136 (no-pure no-rust !)
404 404 data-unused: 448 (pure !)
405 405 data-unused: 448 (rust !)
406 406 data-unused: 0 (no-pure no-rust !)
407 407 data-unused: 0.363% (pure !)
408 408 data-unused: 0.363% (rust !)
409 409 data-unused: 0.000% (no-pure no-rust !)
410 410 $ f --size --sha256 .hg/store/00changelog-*.nd
411 411 .hg/store/00changelog-????????????????.nd: size=123584, sha256=8c6cef6fd3d3fac291968793ee19a4be6d0b8375e9508bd5c7d4a8879e8df180 (glob) (pure !)
412 412 .hg/store/00changelog-????????????????.nd: size=123584, sha256=eb9e9a4bcafdb5e1344bc8a0cbb3288b2106413b8efae6265fb8a7973d7e97f9 (glob) (rust !)
413 413 .hg/store/00changelog-????????????????.nd: size=123136, sha256=4f504f5a834db3811ced50ab3e9e80bcae3581bb0f9b13a7a9f94b7fc34bcebe (glob) (no-pure no-rust !)
General Comments 0
You need to be logged in to leave comments. Login now