##// END OF EJS Templates
share: rework config options to be much clearer and easier...
Pulkit Goyal -
r47050:cc3452d2 default
parent child Browse files
Show More
@@ -1,2583 +1,2578 b''
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,
137 137 configprefix + b'nodates',
138 138 default=False,
139 139 )
140 140 coreconfigitem(
141 141 section,
142 142 configprefix + b'showfunc',
143 143 default=False,
144 144 )
145 145 coreconfigitem(
146 146 section,
147 147 configprefix + b'unified',
148 148 default=None,
149 149 )
150 150 coreconfigitem(
151 151 section,
152 152 configprefix + b'git',
153 153 default=False,
154 154 )
155 155 coreconfigitem(
156 156 section,
157 157 configprefix + b'ignorews',
158 158 default=False,
159 159 )
160 160 coreconfigitem(
161 161 section,
162 162 configprefix + b'ignorewsamount',
163 163 default=False,
164 164 )
165 165 coreconfigitem(
166 166 section,
167 167 configprefix + b'ignoreblanklines',
168 168 default=False,
169 169 )
170 170 coreconfigitem(
171 171 section,
172 172 configprefix + b'ignorewseol',
173 173 default=False,
174 174 )
175 175 coreconfigitem(
176 176 section,
177 177 configprefix + b'nobinary',
178 178 default=False,
179 179 )
180 180 coreconfigitem(
181 181 section,
182 182 configprefix + b'noprefix',
183 183 default=False,
184 184 )
185 185 coreconfigitem(
186 186 section,
187 187 configprefix + b'word-diff',
188 188 default=False,
189 189 )
190 190
191 191
192 192 coreconfigitem(
193 193 b'alias',
194 194 b'.*',
195 195 default=dynamicdefault,
196 196 generic=True,
197 197 )
198 198 coreconfigitem(
199 199 b'auth',
200 200 b'cookiefile',
201 201 default=None,
202 202 )
203 203 _registerdiffopts(section=b'annotate')
204 204 # bookmarks.pushing: internal hack for discovery
205 205 coreconfigitem(
206 206 b'bookmarks',
207 207 b'pushing',
208 208 default=list,
209 209 )
210 210 # bundle.mainreporoot: internal hack for bundlerepo
211 211 coreconfigitem(
212 212 b'bundle',
213 213 b'mainreporoot',
214 214 default=b'',
215 215 )
216 216 coreconfigitem(
217 217 b'censor',
218 218 b'policy',
219 219 default=b'abort',
220 220 experimental=True,
221 221 )
222 222 coreconfigitem(
223 223 b'chgserver',
224 224 b'idletimeout',
225 225 default=3600,
226 226 )
227 227 coreconfigitem(
228 228 b'chgserver',
229 229 b'skiphash',
230 230 default=False,
231 231 )
232 232 coreconfigitem(
233 233 b'cmdserver',
234 234 b'log',
235 235 default=None,
236 236 )
237 237 coreconfigitem(
238 238 b'cmdserver',
239 239 b'max-log-files',
240 240 default=7,
241 241 )
242 242 coreconfigitem(
243 243 b'cmdserver',
244 244 b'max-log-size',
245 245 default=b'1 MB',
246 246 )
247 247 coreconfigitem(
248 248 b'cmdserver',
249 249 b'max-repo-cache',
250 250 default=0,
251 251 experimental=True,
252 252 )
253 253 coreconfigitem(
254 254 b'cmdserver',
255 255 b'message-encodings',
256 256 default=list,
257 257 )
258 258 coreconfigitem(
259 259 b'cmdserver',
260 260 b'track-log',
261 261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
262 262 )
263 263 coreconfigitem(
264 264 b'cmdserver',
265 265 b'shutdown-on-interrupt',
266 266 default=True,
267 267 )
268 268 coreconfigitem(
269 269 b'color',
270 270 b'.*',
271 271 default=None,
272 272 generic=True,
273 273 )
274 274 coreconfigitem(
275 275 b'color',
276 276 b'mode',
277 277 default=b'auto',
278 278 )
279 279 coreconfigitem(
280 280 b'color',
281 281 b'pagermode',
282 282 default=dynamicdefault,
283 283 )
284 284 coreconfigitem(
285 285 b'command-templates',
286 286 b'graphnode',
287 287 default=None,
288 288 alias=[(b'ui', b'graphnodetemplate')],
289 289 )
290 290 coreconfigitem(
291 291 b'command-templates',
292 292 b'log',
293 293 default=None,
294 294 alias=[(b'ui', b'logtemplate')],
295 295 )
296 296 coreconfigitem(
297 297 b'command-templates',
298 298 b'mergemarker',
299 299 default=(
300 300 b'{node|short} '
301 301 b'{ifeq(tags, "tip", "", '
302 302 b'ifeq(tags, "", "", "{tags} "))}'
303 303 b'{if(bookmarks, "{bookmarks} ")}'
304 304 b'{ifeq(branch, "default", "", "{branch} ")}'
305 305 b'- {author|user}: {desc|firstline}'
306 306 ),
307 307 alias=[(b'ui', b'mergemarkertemplate')],
308 308 )
309 309 coreconfigitem(
310 310 b'command-templates',
311 311 b'pre-merge-tool-output',
312 312 default=None,
313 313 alias=[(b'ui', b'pre-merge-tool-output-template')],
314 314 )
315 315 coreconfigitem(
316 316 b'command-templates',
317 317 b'oneline-summary',
318 318 default=None,
319 319 )
320 320 coreconfigitem(
321 321 b'command-templates',
322 322 b'oneline-summary.*',
323 323 default=dynamicdefault,
324 324 generic=True,
325 325 )
326 326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
327 327 coreconfigitem(
328 328 b'commands',
329 329 b'commit.post-status',
330 330 default=False,
331 331 )
332 332 coreconfigitem(
333 333 b'commands',
334 334 b'grep.all-files',
335 335 default=False,
336 336 experimental=True,
337 337 )
338 338 coreconfigitem(
339 339 b'commands',
340 340 b'merge.require-rev',
341 341 default=False,
342 342 )
343 343 coreconfigitem(
344 344 b'commands',
345 345 b'push.require-revs',
346 346 default=False,
347 347 )
348 348 coreconfigitem(
349 349 b'commands',
350 350 b'resolve.confirm',
351 351 default=False,
352 352 )
353 353 coreconfigitem(
354 354 b'commands',
355 355 b'resolve.explicit-re-merge',
356 356 default=False,
357 357 )
358 358 coreconfigitem(
359 359 b'commands',
360 360 b'resolve.mark-check',
361 361 default=b'none',
362 362 )
363 363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
364 364 coreconfigitem(
365 365 b'commands',
366 366 b'show.aliasprefix',
367 367 default=list,
368 368 )
369 369 coreconfigitem(
370 370 b'commands',
371 371 b'status.relative',
372 372 default=False,
373 373 )
374 374 coreconfigitem(
375 375 b'commands',
376 376 b'status.skipstates',
377 377 default=[],
378 378 experimental=True,
379 379 )
380 380 coreconfigitem(
381 381 b'commands',
382 382 b'status.terse',
383 383 default=b'',
384 384 )
385 385 coreconfigitem(
386 386 b'commands',
387 387 b'status.verbose',
388 388 default=False,
389 389 )
390 390 coreconfigitem(
391 391 b'commands',
392 392 b'update.check',
393 393 default=None,
394 394 )
395 395 coreconfigitem(
396 396 b'commands',
397 397 b'update.requiredest',
398 398 default=False,
399 399 )
400 400 coreconfigitem(
401 401 b'committemplate',
402 402 b'.*',
403 403 default=None,
404 404 generic=True,
405 405 )
406 406 coreconfigitem(
407 407 b'convert',
408 408 b'bzr.saverev',
409 409 default=True,
410 410 )
411 411 coreconfigitem(
412 412 b'convert',
413 413 b'cvsps.cache',
414 414 default=True,
415 415 )
416 416 coreconfigitem(
417 417 b'convert',
418 418 b'cvsps.fuzz',
419 419 default=60,
420 420 )
421 421 coreconfigitem(
422 422 b'convert',
423 423 b'cvsps.logencoding',
424 424 default=None,
425 425 )
426 426 coreconfigitem(
427 427 b'convert',
428 428 b'cvsps.mergefrom',
429 429 default=None,
430 430 )
431 431 coreconfigitem(
432 432 b'convert',
433 433 b'cvsps.mergeto',
434 434 default=None,
435 435 )
436 436 coreconfigitem(
437 437 b'convert',
438 438 b'git.committeractions',
439 439 default=lambda: [b'messagedifferent'],
440 440 )
441 441 coreconfigitem(
442 442 b'convert',
443 443 b'git.extrakeys',
444 444 default=list,
445 445 )
446 446 coreconfigitem(
447 447 b'convert',
448 448 b'git.findcopiesharder',
449 449 default=False,
450 450 )
451 451 coreconfigitem(
452 452 b'convert',
453 453 b'git.remoteprefix',
454 454 default=b'remote',
455 455 )
456 456 coreconfigitem(
457 457 b'convert',
458 458 b'git.renamelimit',
459 459 default=400,
460 460 )
461 461 coreconfigitem(
462 462 b'convert',
463 463 b'git.saverev',
464 464 default=True,
465 465 )
466 466 coreconfigitem(
467 467 b'convert',
468 468 b'git.similarity',
469 469 default=50,
470 470 )
471 471 coreconfigitem(
472 472 b'convert',
473 473 b'git.skipsubmodules',
474 474 default=False,
475 475 )
476 476 coreconfigitem(
477 477 b'convert',
478 478 b'hg.clonebranches',
479 479 default=False,
480 480 )
481 481 coreconfigitem(
482 482 b'convert',
483 483 b'hg.ignoreerrors',
484 484 default=False,
485 485 )
486 486 coreconfigitem(
487 487 b'convert',
488 488 b'hg.preserve-hash',
489 489 default=False,
490 490 )
491 491 coreconfigitem(
492 492 b'convert',
493 493 b'hg.revs',
494 494 default=None,
495 495 )
496 496 coreconfigitem(
497 497 b'convert',
498 498 b'hg.saverev',
499 499 default=False,
500 500 )
501 501 coreconfigitem(
502 502 b'convert',
503 503 b'hg.sourcename',
504 504 default=None,
505 505 )
506 506 coreconfigitem(
507 507 b'convert',
508 508 b'hg.startrev',
509 509 default=None,
510 510 )
511 511 coreconfigitem(
512 512 b'convert',
513 513 b'hg.tagsbranch',
514 514 default=b'default',
515 515 )
516 516 coreconfigitem(
517 517 b'convert',
518 518 b'hg.usebranchnames',
519 519 default=True,
520 520 )
521 521 coreconfigitem(
522 522 b'convert',
523 523 b'ignoreancestorcheck',
524 524 default=False,
525 525 experimental=True,
526 526 )
527 527 coreconfigitem(
528 528 b'convert',
529 529 b'localtimezone',
530 530 default=False,
531 531 )
532 532 coreconfigitem(
533 533 b'convert',
534 534 b'p4.encoding',
535 535 default=dynamicdefault,
536 536 )
537 537 coreconfigitem(
538 538 b'convert',
539 539 b'p4.startrev',
540 540 default=0,
541 541 )
542 542 coreconfigitem(
543 543 b'convert',
544 544 b'skiptags',
545 545 default=False,
546 546 )
547 547 coreconfigitem(
548 548 b'convert',
549 549 b'svn.debugsvnlog',
550 550 default=True,
551 551 )
552 552 coreconfigitem(
553 553 b'convert',
554 554 b'svn.trunk',
555 555 default=None,
556 556 )
557 557 coreconfigitem(
558 558 b'convert',
559 559 b'svn.tags',
560 560 default=None,
561 561 )
562 562 coreconfigitem(
563 563 b'convert',
564 564 b'svn.branches',
565 565 default=None,
566 566 )
567 567 coreconfigitem(
568 568 b'convert',
569 569 b'svn.startrev',
570 570 default=0,
571 571 )
572 572 coreconfigitem(
573 573 b'debug',
574 574 b'dirstate.delaywrite',
575 575 default=0,
576 576 )
577 577 coreconfigitem(
578 578 b'defaults',
579 579 b'.*',
580 580 default=None,
581 581 generic=True,
582 582 )
583 583 coreconfigitem(
584 584 b'devel',
585 585 b'all-warnings',
586 586 default=False,
587 587 )
588 588 coreconfigitem(
589 589 b'devel',
590 590 b'bundle2.debug',
591 591 default=False,
592 592 )
593 593 coreconfigitem(
594 594 b'devel',
595 595 b'bundle.delta',
596 596 default=b'',
597 597 )
598 598 coreconfigitem(
599 599 b'devel',
600 600 b'cache-vfs',
601 601 default=None,
602 602 )
603 603 coreconfigitem(
604 604 b'devel',
605 605 b'check-locks',
606 606 default=False,
607 607 )
608 608 coreconfigitem(
609 609 b'devel',
610 610 b'check-relroot',
611 611 default=False,
612 612 )
613 613 coreconfigitem(
614 614 b'devel',
615 615 b'default-date',
616 616 default=None,
617 617 )
618 618 coreconfigitem(
619 619 b'devel',
620 620 b'deprec-warn',
621 621 default=False,
622 622 )
623 623 coreconfigitem(
624 624 b'devel',
625 625 b'disableloaddefaultcerts',
626 626 default=False,
627 627 )
628 628 coreconfigitem(
629 629 b'devel',
630 630 b'warn-empty-changegroup',
631 631 default=False,
632 632 )
633 633 coreconfigitem(
634 634 b'devel',
635 635 b'legacy.exchange',
636 636 default=list,
637 637 )
638 638 # When True, revlogs use a special reference version of the nodemap, that is not
639 639 # performant but is "known" to behave properly.
640 640 coreconfigitem(
641 641 b'devel',
642 642 b'persistent-nodemap',
643 643 default=False,
644 644 )
645 645 coreconfigitem(
646 646 b'devel',
647 647 b'servercafile',
648 648 default=b'',
649 649 )
650 650 coreconfigitem(
651 651 b'devel',
652 652 b'serverexactprotocol',
653 653 default=b'',
654 654 )
655 655 coreconfigitem(
656 656 b'devel',
657 657 b'serverrequirecert',
658 658 default=False,
659 659 )
660 660 coreconfigitem(
661 661 b'devel',
662 662 b'strip-obsmarkers',
663 663 default=True,
664 664 )
665 665 coreconfigitem(
666 666 b'devel',
667 667 b'warn-config',
668 668 default=None,
669 669 )
670 670 coreconfigitem(
671 671 b'devel',
672 672 b'warn-config-default',
673 673 default=None,
674 674 )
675 675 coreconfigitem(
676 676 b'devel',
677 677 b'user.obsmarker',
678 678 default=None,
679 679 )
680 680 coreconfigitem(
681 681 b'devel',
682 682 b'warn-config-unknown',
683 683 default=None,
684 684 )
685 685 coreconfigitem(
686 686 b'devel',
687 687 b'debug.copies',
688 688 default=False,
689 689 )
690 690 coreconfigitem(
691 691 b'devel',
692 692 b'debug.extensions',
693 693 default=False,
694 694 )
695 695 coreconfigitem(
696 696 b'devel',
697 697 b'debug.repo-filters',
698 698 default=False,
699 699 )
700 700 coreconfigitem(
701 701 b'devel',
702 702 b'debug.peer-request',
703 703 default=False,
704 704 )
705 705 # If discovery.exchange-heads is False, the discovery will not start with
706 706 # remote head fetching and local head querying.
707 707 coreconfigitem(
708 708 b'devel',
709 709 b'discovery.exchange-heads',
710 710 default=True,
711 711 )
712 712 # If discovery.grow-sample is False, the sample size used in set discovery will
713 713 # not be increased through the process
714 714 coreconfigitem(
715 715 b'devel',
716 716 b'discovery.grow-sample',
717 717 default=True,
718 718 )
719 719 # discovery.grow-sample.rate control the rate at which the sample grow
720 720 coreconfigitem(
721 721 b'devel',
722 722 b'discovery.grow-sample.rate',
723 723 default=1.05,
724 724 )
725 725 # If discovery.randomize is False, random sampling during discovery are
726 726 # deterministic. It is meant for integration tests.
727 727 coreconfigitem(
728 728 b'devel',
729 729 b'discovery.randomize',
730 730 default=True,
731 731 )
732 732 _registerdiffopts(section=b'diff')
733 733 coreconfigitem(
734 734 b'email',
735 735 b'bcc',
736 736 default=None,
737 737 )
738 738 coreconfigitem(
739 739 b'email',
740 740 b'cc',
741 741 default=None,
742 742 )
743 743 coreconfigitem(
744 744 b'email',
745 745 b'charsets',
746 746 default=list,
747 747 )
748 748 coreconfigitem(
749 749 b'email',
750 750 b'from',
751 751 default=None,
752 752 )
753 753 coreconfigitem(
754 754 b'email',
755 755 b'method',
756 756 default=b'smtp',
757 757 )
758 758 coreconfigitem(
759 759 b'email',
760 760 b'reply-to',
761 761 default=None,
762 762 )
763 763 coreconfigitem(
764 764 b'email',
765 765 b'to',
766 766 default=None,
767 767 )
768 768 coreconfigitem(
769 769 b'experimental',
770 770 b'archivemetatemplate',
771 771 default=dynamicdefault,
772 772 )
773 773 coreconfigitem(
774 774 b'experimental',
775 775 b'auto-publish',
776 776 default=b'publish',
777 777 )
778 778 coreconfigitem(
779 779 b'experimental',
780 780 b'bundle-phases',
781 781 default=False,
782 782 )
783 783 coreconfigitem(
784 784 b'experimental',
785 785 b'bundle2-advertise',
786 786 default=True,
787 787 )
788 788 coreconfigitem(
789 789 b'experimental',
790 790 b'bundle2-output-capture',
791 791 default=False,
792 792 )
793 793 coreconfigitem(
794 794 b'experimental',
795 795 b'bundle2.pushback',
796 796 default=False,
797 797 )
798 798 coreconfigitem(
799 799 b'experimental',
800 800 b'bundle2lazylocking',
801 801 default=False,
802 802 )
803 803 coreconfigitem(
804 804 b'experimental',
805 805 b'bundlecomplevel',
806 806 default=None,
807 807 )
808 808 coreconfigitem(
809 809 b'experimental',
810 810 b'bundlecomplevel.bzip2',
811 811 default=None,
812 812 )
813 813 coreconfigitem(
814 814 b'experimental',
815 815 b'bundlecomplevel.gzip',
816 816 default=None,
817 817 )
818 818 coreconfigitem(
819 819 b'experimental',
820 820 b'bundlecomplevel.none',
821 821 default=None,
822 822 )
823 823 coreconfigitem(
824 824 b'experimental',
825 825 b'bundlecomplevel.zstd',
826 826 default=None,
827 827 )
828 828 coreconfigitem(
829 829 b'experimental',
830 830 b'changegroup3',
831 831 default=False,
832 832 )
833 833 coreconfigitem(
834 834 b'experimental',
835 835 b'cleanup-as-archived',
836 836 default=False,
837 837 )
838 838 coreconfigitem(
839 839 b'experimental',
840 840 b'clientcompressionengines',
841 841 default=list,
842 842 )
843 843 coreconfigitem(
844 844 b'experimental',
845 845 b'copytrace',
846 846 default=b'on',
847 847 )
848 848 coreconfigitem(
849 849 b'experimental',
850 850 b'copytrace.movecandidateslimit',
851 851 default=100,
852 852 )
853 853 coreconfigitem(
854 854 b'experimental',
855 855 b'copytrace.sourcecommitlimit',
856 856 default=100,
857 857 )
858 858 coreconfigitem(
859 859 b'experimental',
860 860 b'copies.read-from',
861 861 default=b"filelog-only",
862 862 )
863 863 coreconfigitem(
864 864 b'experimental',
865 865 b'copies.write-to',
866 866 default=b'filelog-only',
867 867 )
868 868 coreconfigitem(
869 869 b'experimental',
870 870 b'crecordtest',
871 871 default=None,
872 872 )
873 873 coreconfigitem(
874 874 b'experimental',
875 875 b'directaccess',
876 876 default=False,
877 877 )
878 878 coreconfigitem(
879 879 b'experimental',
880 880 b'directaccess.revnums',
881 881 default=False,
882 882 )
883 883 coreconfigitem(
884 884 b'experimental',
885 885 b'editortmpinhg',
886 886 default=False,
887 887 )
888 888 coreconfigitem(
889 889 b'experimental',
890 890 b'evolution',
891 891 default=list,
892 892 )
893 893 coreconfigitem(
894 894 b'experimental',
895 895 b'evolution.allowdivergence',
896 896 default=False,
897 897 alias=[(b'experimental', b'allowdivergence')],
898 898 )
899 899 coreconfigitem(
900 900 b'experimental',
901 901 b'evolution.allowunstable',
902 902 default=None,
903 903 )
904 904 coreconfigitem(
905 905 b'experimental',
906 906 b'evolution.createmarkers',
907 907 default=None,
908 908 )
909 909 coreconfigitem(
910 910 b'experimental',
911 911 b'evolution.effect-flags',
912 912 default=True,
913 913 alias=[(b'experimental', b'effect-flags')],
914 914 )
915 915 coreconfigitem(
916 916 b'experimental',
917 917 b'evolution.exchange',
918 918 default=None,
919 919 )
920 920 coreconfigitem(
921 921 b'experimental',
922 922 b'evolution.bundle-obsmarker',
923 923 default=False,
924 924 )
925 925 coreconfigitem(
926 926 b'experimental',
927 927 b'evolution.bundle-obsmarker:mandatory',
928 928 default=True,
929 929 )
930 930 coreconfigitem(
931 931 b'experimental',
932 932 b'log.topo',
933 933 default=False,
934 934 )
935 935 coreconfigitem(
936 936 b'experimental',
937 937 b'evolution.report-instabilities',
938 938 default=True,
939 939 )
940 940 coreconfigitem(
941 941 b'experimental',
942 942 b'evolution.track-operation',
943 943 default=True,
944 944 )
945 945 # repo-level config to exclude a revset visibility
946 946 #
947 947 # The target use case is to use `share` to expose different subset of the same
948 948 # repository, especially server side. See also `server.view`.
949 949 coreconfigitem(
950 950 b'experimental',
951 951 b'extra-filter-revs',
952 952 default=None,
953 953 )
954 954 coreconfigitem(
955 955 b'experimental',
956 956 b'maxdeltachainspan',
957 957 default=-1,
958 958 )
959 959 # tracks files which were undeleted (merge might delete them but we explicitly
960 960 # kept/undeleted them) and creates new filenodes for them
961 961 coreconfigitem(
962 962 b'experimental',
963 963 b'merge-track-salvaged',
964 964 default=False,
965 965 )
966 966 coreconfigitem(
967 967 b'experimental',
968 968 b'mergetempdirprefix',
969 969 default=None,
970 970 )
971 971 coreconfigitem(
972 972 b'experimental',
973 973 b'mmapindexthreshold',
974 974 default=None,
975 975 )
976 976 coreconfigitem(
977 977 b'experimental',
978 978 b'narrow',
979 979 default=False,
980 980 )
981 981 coreconfigitem(
982 982 b'experimental',
983 983 b'nonnormalparanoidcheck',
984 984 default=False,
985 985 )
986 986 coreconfigitem(
987 987 b'experimental',
988 988 b'exportableenviron',
989 989 default=list,
990 990 )
991 991 coreconfigitem(
992 992 b'experimental',
993 993 b'extendedheader.index',
994 994 default=None,
995 995 )
996 996 coreconfigitem(
997 997 b'experimental',
998 998 b'extendedheader.similarity',
999 999 default=False,
1000 1000 )
1001 1001 coreconfigitem(
1002 1002 b'experimental',
1003 1003 b'graphshorten',
1004 1004 default=False,
1005 1005 )
1006 1006 coreconfigitem(
1007 1007 b'experimental',
1008 1008 b'graphstyle.parent',
1009 1009 default=dynamicdefault,
1010 1010 )
1011 1011 coreconfigitem(
1012 1012 b'experimental',
1013 1013 b'graphstyle.missing',
1014 1014 default=dynamicdefault,
1015 1015 )
1016 1016 coreconfigitem(
1017 1017 b'experimental',
1018 1018 b'graphstyle.grandparent',
1019 1019 default=dynamicdefault,
1020 1020 )
1021 1021 coreconfigitem(
1022 1022 b'experimental',
1023 1023 b'hook-track-tags',
1024 1024 default=False,
1025 1025 )
1026 1026 coreconfigitem(
1027 1027 b'experimental',
1028 1028 b'httppeer.advertise-v2',
1029 1029 default=False,
1030 1030 )
1031 1031 coreconfigitem(
1032 1032 b'experimental',
1033 1033 b'httppeer.v2-encoder-order',
1034 1034 default=None,
1035 1035 )
1036 1036 coreconfigitem(
1037 1037 b'experimental',
1038 1038 b'httppostargs',
1039 1039 default=False,
1040 1040 )
1041 1041 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1042 1042 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1043 1043
1044 1044 coreconfigitem(
1045 1045 b'experimental',
1046 1046 b'obsmarkers-exchange-debug',
1047 1047 default=False,
1048 1048 )
1049 1049 coreconfigitem(
1050 1050 b'experimental',
1051 1051 b'remotenames',
1052 1052 default=False,
1053 1053 )
1054 1054 coreconfigitem(
1055 1055 b'experimental',
1056 1056 b'removeemptydirs',
1057 1057 default=True,
1058 1058 )
1059 1059 coreconfigitem(
1060 1060 b'experimental',
1061 1061 b'revert.interactive.select-to-keep',
1062 1062 default=False,
1063 1063 )
1064 1064 coreconfigitem(
1065 1065 b'experimental',
1066 1066 b'revisions.prefixhexnode',
1067 1067 default=False,
1068 1068 )
1069 1069 coreconfigitem(
1070 1070 b'experimental',
1071 1071 b'revlogv2',
1072 1072 default=None,
1073 1073 )
1074 1074 coreconfigitem(
1075 1075 b'experimental',
1076 1076 b'revisions.disambiguatewithin',
1077 1077 default=None,
1078 1078 )
1079 1079 coreconfigitem(
1080 1080 b'experimental',
1081 1081 b'rust.index',
1082 1082 default=False,
1083 1083 )
1084 1084 coreconfigitem(
1085 1085 b'experimental',
1086 1086 b'server.filesdata.recommended-batch-size',
1087 1087 default=50000,
1088 1088 )
1089 1089 coreconfigitem(
1090 1090 b'experimental',
1091 1091 b'server.manifestdata.recommended-batch-size',
1092 1092 default=100000,
1093 1093 )
1094 1094 coreconfigitem(
1095 1095 b'experimental',
1096 1096 b'server.stream-narrow-clones',
1097 1097 default=False,
1098 1098 )
1099 1099 coreconfigitem(
1100 1100 b'experimental',
1101 b'sharesafe-auto-downgrade-shares',
1102 default=False,
1103 )
1104 coreconfigitem(
1105 b'experimental',
1106 b'sharesafe-auto-upgrade-shares',
1107 default=False,
1108 )
1109 coreconfigitem(
1110 b'experimental',
1111 b'sharesafe-auto-upgrade-fail-error',
1112 default=False,
1113 )
1114 coreconfigitem(
1115 b'experimental',
1116 1101 b'sharesafe-warn-outdated-shares',
1117 1102 default=True,
1118 1103 )
1119 1104 coreconfigitem(
1120 1105 b'experimental',
1121 1106 b'single-head-per-branch',
1122 1107 default=False,
1123 1108 )
1124 1109 coreconfigitem(
1125 1110 b'experimental',
1126 1111 b'single-head-per-branch:account-closed-heads',
1127 1112 default=False,
1128 1113 )
1129 1114 coreconfigitem(
1130 1115 b'experimental',
1131 1116 b'single-head-per-branch:public-changes-only',
1132 1117 default=False,
1133 1118 )
1134 1119 coreconfigitem(
1135 1120 b'experimental',
1136 1121 b'sshserver.support-v2',
1137 1122 default=False,
1138 1123 )
1139 1124 coreconfigitem(
1140 1125 b'experimental',
1141 1126 b'sparse-read',
1142 1127 default=False,
1143 1128 )
1144 1129 coreconfigitem(
1145 1130 b'experimental',
1146 1131 b'sparse-read.density-threshold',
1147 1132 default=0.50,
1148 1133 )
1149 1134 coreconfigitem(
1150 1135 b'experimental',
1151 1136 b'sparse-read.min-gap-size',
1152 1137 default=b'65K',
1153 1138 )
1154 1139 coreconfigitem(
1155 1140 b'experimental',
1156 1141 b'treemanifest',
1157 1142 default=False,
1158 1143 )
1159 1144 coreconfigitem(
1160 1145 b'experimental',
1161 1146 b'update.atomic-file',
1162 1147 default=False,
1163 1148 )
1164 1149 coreconfigitem(
1165 1150 b'experimental',
1166 1151 b'sshpeer.advertise-v2',
1167 1152 default=False,
1168 1153 )
1169 1154 coreconfigitem(
1170 1155 b'experimental',
1171 1156 b'web.apiserver',
1172 1157 default=False,
1173 1158 )
1174 1159 coreconfigitem(
1175 1160 b'experimental',
1176 1161 b'web.api.http-v2',
1177 1162 default=False,
1178 1163 )
1179 1164 coreconfigitem(
1180 1165 b'experimental',
1181 1166 b'web.api.debugreflect',
1182 1167 default=False,
1183 1168 )
1184 1169 coreconfigitem(
1185 1170 b'experimental',
1186 1171 b'worker.wdir-get-thread-safe',
1187 1172 default=False,
1188 1173 )
1189 1174 coreconfigitem(
1190 1175 b'experimental',
1191 1176 b'worker.repository-upgrade',
1192 1177 default=False,
1193 1178 )
1194 1179 coreconfigitem(
1195 1180 b'experimental',
1196 1181 b'xdiff',
1197 1182 default=False,
1198 1183 )
1199 1184 coreconfigitem(
1200 1185 b'extensions',
1201 1186 b'.*',
1202 1187 default=None,
1203 1188 generic=True,
1204 1189 )
1205 1190 coreconfigitem(
1206 1191 b'extdata',
1207 1192 b'.*',
1208 1193 default=None,
1209 1194 generic=True,
1210 1195 )
1211 1196 coreconfigitem(
1212 1197 b'format',
1213 1198 b'bookmarks-in-store',
1214 1199 default=False,
1215 1200 )
1216 1201 coreconfigitem(
1217 1202 b'format',
1218 1203 b'chunkcachesize',
1219 1204 default=None,
1220 1205 experimental=True,
1221 1206 )
1222 1207 coreconfigitem(
1223 1208 b'format',
1224 1209 b'dotencode',
1225 1210 default=True,
1226 1211 )
1227 1212 coreconfigitem(
1228 1213 b'format',
1229 1214 b'generaldelta',
1230 1215 default=False,
1231 1216 experimental=True,
1232 1217 )
1233 1218 coreconfigitem(
1234 1219 b'format',
1235 1220 b'manifestcachesize',
1236 1221 default=None,
1237 1222 experimental=True,
1238 1223 )
1239 1224 coreconfigitem(
1240 1225 b'format',
1241 1226 b'maxchainlen',
1242 1227 default=dynamicdefault,
1243 1228 experimental=True,
1244 1229 )
1245 1230 coreconfigitem(
1246 1231 b'format',
1247 1232 b'obsstore-version',
1248 1233 default=None,
1249 1234 )
1250 1235 coreconfigitem(
1251 1236 b'format',
1252 1237 b'sparse-revlog',
1253 1238 default=True,
1254 1239 )
1255 1240 coreconfigitem(
1256 1241 b'format',
1257 1242 b'revlog-compression',
1258 1243 default=lambda: [b'zlib'],
1259 1244 alias=[(b'experimental', b'format.compression')],
1260 1245 )
1261 1246 coreconfigitem(
1262 1247 b'format',
1263 1248 b'usefncache',
1264 1249 default=True,
1265 1250 )
1266 1251 coreconfigitem(
1267 1252 b'format',
1268 1253 b'usegeneraldelta',
1269 1254 default=True,
1270 1255 )
1271 1256 coreconfigitem(
1272 1257 b'format',
1273 1258 b'usestore',
1274 1259 default=True,
1275 1260 )
1276 1261 coreconfigitem(
1277 1262 b'format',
1278 1263 b'use-persistent-nodemap',
1279 1264 default=False,
1280 1265 )
1281 1266 coreconfigitem(
1282 1267 b'format',
1283 1268 b'exp-use-copies-side-data-changeset',
1284 1269 default=False,
1285 1270 experimental=True,
1286 1271 )
1287 1272 coreconfigitem(
1288 1273 b'format',
1289 1274 b'exp-use-side-data',
1290 1275 default=False,
1291 1276 experimental=True,
1292 1277 )
1293 1278 coreconfigitem(
1294 1279 b'format',
1295 1280 b'exp-share-safe',
1296 1281 default=False,
1297 1282 experimental=True,
1298 1283 )
1299 1284 coreconfigitem(
1300 1285 b'format',
1301 1286 b'internal-phase',
1302 1287 default=False,
1303 1288 experimental=True,
1304 1289 )
1305 1290 coreconfigitem(
1306 1291 b'fsmonitor',
1307 1292 b'warn_when_unused',
1308 1293 default=True,
1309 1294 )
1310 1295 coreconfigitem(
1311 1296 b'fsmonitor',
1312 1297 b'warn_update_file_count',
1313 1298 default=50000,
1314 1299 )
1315 1300 coreconfigitem(
1316 1301 b'fsmonitor',
1317 1302 b'warn_update_file_count_rust',
1318 1303 default=400000,
1319 1304 )
1320 1305 coreconfigitem(
1321 1306 b'help',
1322 1307 br'hidden-command\..*',
1323 1308 default=False,
1324 1309 generic=True,
1325 1310 )
1326 1311 coreconfigitem(
1327 1312 b'help',
1328 1313 br'hidden-topic\..*',
1329 1314 default=False,
1330 1315 generic=True,
1331 1316 )
1332 1317 coreconfigitem(
1333 1318 b'hooks',
1334 1319 b'.*',
1335 1320 default=dynamicdefault,
1336 1321 generic=True,
1337 1322 )
1338 1323 coreconfigitem(
1339 1324 b'hgweb-paths',
1340 1325 b'.*',
1341 1326 default=list,
1342 1327 generic=True,
1343 1328 )
1344 1329 coreconfigitem(
1345 1330 b'hostfingerprints',
1346 1331 b'.*',
1347 1332 default=list,
1348 1333 generic=True,
1349 1334 )
1350 1335 coreconfigitem(
1351 1336 b'hostsecurity',
1352 1337 b'ciphers',
1353 1338 default=None,
1354 1339 )
1355 1340 coreconfigitem(
1356 1341 b'hostsecurity',
1357 1342 b'minimumprotocol',
1358 1343 default=dynamicdefault,
1359 1344 )
1360 1345 coreconfigitem(
1361 1346 b'hostsecurity',
1362 1347 b'.*:minimumprotocol$',
1363 1348 default=dynamicdefault,
1364 1349 generic=True,
1365 1350 )
1366 1351 coreconfigitem(
1367 1352 b'hostsecurity',
1368 1353 b'.*:ciphers$',
1369 1354 default=dynamicdefault,
1370 1355 generic=True,
1371 1356 )
1372 1357 coreconfigitem(
1373 1358 b'hostsecurity',
1374 1359 b'.*:fingerprints$',
1375 1360 default=list,
1376 1361 generic=True,
1377 1362 )
1378 1363 coreconfigitem(
1379 1364 b'hostsecurity',
1380 1365 b'.*:verifycertsfile$',
1381 1366 default=None,
1382 1367 generic=True,
1383 1368 )
1384 1369
1385 1370 coreconfigitem(
1386 1371 b'http_proxy',
1387 1372 b'always',
1388 1373 default=False,
1389 1374 )
1390 1375 coreconfigitem(
1391 1376 b'http_proxy',
1392 1377 b'host',
1393 1378 default=None,
1394 1379 )
1395 1380 coreconfigitem(
1396 1381 b'http_proxy',
1397 1382 b'no',
1398 1383 default=list,
1399 1384 )
1400 1385 coreconfigitem(
1401 1386 b'http_proxy',
1402 1387 b'passwd',
1403 1388 default=None,
1404 1389 )
1405 1390 coreconfigitem(
1406 1391 b'http_proxy',
1407 1392 b'user',
1408 1393 default=None,
1409 1394 )
1410 1395
1411 1396 coreconfigitem(
1412 1397 b'http',
1413 1398 b'timeout',
1414 1399 default=None,
1415 1400 )
1416 1401
1417 1402 coreconfigitem(
1418 1403 b'logtoprocess',
1419 1404 b'commandexception',
1420 1405 default=None,
1421 1406 )
1422 1407 coreconfigitem(
1423 1408 b'logtoprocess',
1424 1409 b'commandfinish',
1425 1410 default=None,
1426 1411 )
1427 1412 coreconfigitem(
1428 1413 b'logtoprocess',
1429 1414 b'command',
1430 1415 default=None,
1431 1416 )
1432 1417 coreconfigitem(
1433 1418 b'logtoprocess',
1434 1419 b'develwarn',
1435 1420 default=None,
1436 1421 )
1437 1422 coreconfigitem(
1438 1423 b'logtoprocess',
1439 1424 b'uiblocked',
1440 1425 default=None,
1441 1426 )
1442 1427 coreconfigitem(
1443 1428 b'merge',
1444 1429 b'checkunknown',
1445 1430 default=b'abort',
1446 1431 )
1447 1432 coreconfigitem(
1448 1433 b'merge',
1449 1434 b'checkignored',
1450 1435 default=b'abort',
1451 1436 )
1452 1437 coreconfigitem(
1453 1438 b'experimental',
1454 1439 b'merge.checkpathconflicts',
1455 1440 default=False,
1456 1441 )
1457 1442 coreconfigitem(
1458 1443 b'merge',
1459 1444 b'followcopies',
1460 1445 default=True,
1461 1446 )
1462 1447 coreconfigitem(
1463 1448 b'merge',
1464 1449 b'on-failure',
1465 1450 default=b'continue',
1466 1451 )
1467 1452 coreconfigitem(
1468 1453 b'merge',
1469 1454 b'preferancestor',
1470 1455 default=lambda: [b'*'],
1471 1456 experimental=True,
1472 1457 )
1473 1458 coreconfigitem(
1474 1459 b'merge',
1475 1460 b'strict-capability-check',
1476 1461 default=False,
1477 1462 )
1478 1463 coreconfigitem(
1479 1464 b'merge-tools',
1480 1465 b'.*',
1481 1466 default=None,
1482 1467 generic=True,
1483 1468 )
1484 1469 coreconfigitem(
1485 1470 b'merge-tools',
1486 1471 br'.*\.args$',
1487 1472 default=b"$local $base $other",
1488 1473 generic=True,
1489 1474 priority=-1,
1490 1475 )
1491 1476 coreconfigitem(
1492 1477 b'merge-tools',
1493 1478 br'.*\.binary$',
1494 1479 default=False,
1495 1480 generic=True,
1496 1481 priority=-1,
1497 1482 )
1498 1483 coreconfigitem(
1499 1484 b'merge-tools',
1500 1485 br'.*\.check$',
1501 1486 default=list,
1502 1487 generic=True,
1503 1488 priority=-1,
1504 1489 )
1505 1490 coreconfigitem(
1506 1491 b'merge-tools',
1507 1492 br'.*\.checkchanged$',
1508 1493 default=False,
1509 1494 generic=True,
1510 1495 priority=-1,
1511 1496 )
1512 1497 coreconfigitem(
1513 1498 b'merge-tools',
1514 1499 br'.*\.executable$',
1515 1500 default=dynamicdefault,
1516 1501 generic=True,
1517 1502 priority=-1,
1518 1503 )
1519 1504 coreconfigitem(
1520 1505 b'merge-tools',
1521 1506 br'.*\.fixeol$',
1522 1507 default=False,
1523 1508 generic=True,
1524 1509 priority=-1,
1525 1510 )
1526 1511 coreconfigitem(
1527 1512 b'merge-tools',
1528 1513 br'.*\.gui$',
1529 1514 default=False,
1530 1515 generic=True,
1531 1516 priority=-1,
1532 1517 )
1533 1518 coreconfigitem(
1534 1519 b'merge-tools',
1535 1520 br'.*\.mergemarkers$',
1536 1521 default=b'basic',
1537 1522 generic=True,
1538 1523 priority=-1,
1539 1524 )
1540 1525 coreconfigitem(
1541 1526 b'merge-tools',
1542 1527 br'.*\.mergemarkertemplate$',
1543 1528 default=dynamicdefault, # take from command-templates.mergemarker
1544 1529 generic=True,
1545 1530 priority=-1,
1546 1531 )
1547 1532 coreconfigitem(
1548 1533 b'merge-tools',
1549 1534 br'.*\.priority$',
1550 1535 default=0,
1551 1536 generic=True,
1552 1537 priority=-1,
1553 1538 )
1554 1539 coreconfigitem(
1555 1540 b'merge-tools',
1556 1541 br'.*\.premerge$',
1557 1542 default=dynamicdefault,
1558 1543 generic=True,
1559 1544 priority=-1,
1560 1545 )
1561 1546 coreconfigitem(
1562 1547 b'merge-tools',
1563 1548 br'.*\.symlink$',
1564 1549 default=False,
1565 1550 generic=True,
1566 1551 priority=-1,
1567 1552 )
1568 1553 coreconfigitem(
1569 1554 b'pager',
1570 1555 b'attend-.*',
1571 1556 default=dynamicdefault,
1572 1557 generic=True,
1573 1558 )
1574 1559 coreconfigitem(
1575 1560 b'pager',
1576 1561 b'ignore',
1577 1562 default=list,
1578 1563 )
1579 1564 coreconfigitem(
1580 1565 b'pager',
1581 1566 b'pager',
1582 1567 default=dynamicdefault,
1583 1568 )
1584 1569 coreconfigitem(
1585 1570 b'patch',
1586 1571 b'eol',
1587 1572 default=b'strict',
1588 1573 )
1589 1574 coreconfigitem(
1590 1575 b'patch',
1591 1576 b'fuzz',
1592 1577 default=2,
1593 1578 )
1594 1579 coreconfigitem(
1595 1580 b'paths',
1596 1581 b'default',
1597 1582 default=None,
1598 1583 )
1599 1584 coreconfigitem(
1600 1585 b'paths',
1601 1586 b'default-push',
1602 1587 default=None,
1603 1588 )
1604 1589 coreconfigitem(
1605 1590 b'paths',
1606 1591 b'.*',
1607 1592 default=None,
1608 1593 generic=True,
1609 1594 )
1610 1595 coreconfigitem(
1611 1596 b'phases',
1612 1597 b'checksubrepos',
1613 1598 default=b'follow',
1614 1599 )
1615 1600 coreconfigitem(
1616 1601 b'phases',
1617 1602 b'new-commit',
1618 1603 default=b'draft',
1619 1604 )
1620 1605 coreconfigitem(
1621 1606 b'phases',
1622 1607 b'publish',
1623 1608 default=True,
1624 1609 )
1625 1610 coreconfigitem(
1626 1611 b'profiling',
1627 1612 b'enabled',
1628 1613 default=False,
1629 1614 )
1630 1615 coreconfigitem(
1631 1616 b'profiling',
1632 1617 b'format',
1633 1618 default=b'text',
1634 1619 )
1635 1620 coreconfigitem(
1636 1621 b'profiling',
1637 1622 b'freq',
1638 1623 default=1000,
1639 1624 )
1640 1625 coreconfigitem(
1641 1626 b'profiling',
1642 1627 b'limit',
1643 1628 default=30,
1644 1629 )
1645 1630 coreconfigitem(
1646 1631 b'profiling',
1647 1632 b'nested',
1648 1633 default=0,
1649 1634 )
1650 1635 coreconfigitem(
1651 1636 b'profiling',
1652 1637 b'output',
1653 1638 default=None,
1654 1639 )
1655 1640 coreconfigitem(
1656 1641 b'profiling',
1657 1642 b'showmax',
1658 1643 default=0.999,
1659 1644 )
1660 1645 coreconfigitem(
1661 1646 b'profiling',
1662 1647 b'showmin',
1663 1648 default=dynamicdefault,
1664 1649 )
1665 1650 coreconfigitem(
1666 1651 b'profiling',
1667 1652 b'showtime',
1668 1653 default=True,
1669 1654 )
1670 1655 coreconfigitem(
1671 1656 b'profiling',
1672 1657 b'sort',
1673 1658 default=b'inlinetime',
1674 1659 )
1675 1660 coreconfigitem(
1676 1661 b'profiling',
1677 1662 b'statformat',
1678 1663 default=b'hotpath',
1679 1664 )
1680 1665 coreconfigitem(
1681 1666 b'profiling',
1682 1667 b'time-track',
1683 1668 default=dynamicdefault,
1684 1669 )
1685 1670 coreconfigitem(
1686 1671 b'profiling',
1687 1672 b'type',
1688 1673 default=b'stat',
1689 1674 )
1690 1675 coreconfigitem(
1691 1676 b'progress',
1692 1677 b'assume-tty',
1693 1678 default=False,
1694 1679 )
1695 1680 coreconfigitem(
1696 1681 b'progress',
1697 1682 b'changedelay',
1698 1683 default=1,
1699 1684 )
1700 1685 coreconfigitem(
1701 1686 b'progress',
1702 1687 b'clear-complete',
1703 1688 default=True,
1704 1689 )
1705 1690 coreconfigitem(
1706 1691 b'progress',
1707 1692 b'debug',
1708 1693 default=False,
1709 1694 )
1710 1695 coreconfigitem(
1711 1696 b'progress',
1712 1697 b'delay',
1713 1698 default=3,
1714 1699 )
1715 1700 coreconfigitem(
1716 1701 b'progress',
1717 1702 b'disable',
1718 1703 default=False,
1719 1704 )
1720 1705 coreconfigitem(
1721 1706 b'progress',
1722 1707 b'estimateinterval',
1723 1708 default=60.0,
1724 1709 )
1725 1710 coreconfigitem(
1726 1711 b'progress',
1727 1712 b'format',
1728 1713 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1729 1714 )
1730 1715 coreconfigitem(
1731 1716 b'progress',
1732 1717 b'refresh',
1733 1718 default=0.1,
1734 1719 )
1735 1720 coreconfigitem(
1736 1721 b'progress',
1737 1722 b'width',
1738 1723 default=dynamicdefault,
1739 1724 )
1740 1725 coreconfigitem(
1741 1726 b'pull',
1742 1727 b'confirm',
1743 1728 default=False,
1744 1729 )
1745 1730 coreconfigitem(
1746 1731 b'push',
1747 1732 b'pushvars.server',
1748 1733 default=False,
1749 1734 )
1750 1735 coreconfigitem(
1751 1736 b'rewrite',
1752 1737 b'backup-bundle',
1753 1738 default=True,
1754 1739 alias=[(b'ui', b'history-editing-backup')],
1755 1740 )
1756 1741 coreconfigitem(
1757 1742 b'rewrite',
1758 1743 b'update-timestamp',
1759 1744 default=False,
1760 1745 )
1761 1746 coreconfigitem(
1762 1747 b'rewrite',
1763 1748 b'empty-successor',
1764 1749 default=b'skip',
1765 1750 experimental=True,
1766 1751 )
1767 1752 coreconfigitem(
1768 1753 b'storage',
1769 1754 b'new-repo-backend',
1770 1755 default=b'revlogv1',
1771 1756 experimental=True,
1772 1757 )
1773 1758 coreconfigitem(
1774 1759 b'storage',
1775 1760 b'revlog.optimize-delta-parent-choice',
1776 1761 default=True,
1777 1762 alias=[(b'format', b'aggressivemergedeltas')],
1778 1763 )
1779 1764 # experimental as long as rust is experimental (or a C version is implemented)
1780 1765 coreconfigitem(
1781 1766 b'storage',
1782 1767 b'revlog.persistent-nodemap.mmap',
1783 1768 default=True,
1784 1769 )
1785 1770 # experimental as long as format.use-persistent-nodemap is.
1786 1771 coreconfigitem(
1787 1772 b'storage',
1788 1773 b'revlog.persistent-nodemap.slow-path',
1789 1774 default=b"abort",
1790 1775 )
1791 1776
1792 1777 coreconfigitem(
1793 1778 b'storage',
1794 1779 b'revlog.reuse-external-delta',
1795 1780 default=True,
1796 1781 )
1797 1782 coreconfigitem(
1798 1783 b'storage',
1799 1784 b'revlog.reuse-external-delta-parent',
1800 1785 default=None,
1801 1786 )
1802 1787 coreconfigitem(
1803 1788 b'storage',
1804 1789 b'revlog.zlib.level',
1805 1790 default=None,
1806 1791 )
1807 1792 coreconfigitem(
1808 1793 b'storage',
1809 1794 b'revlog.zstd.level',
1810 1795 default=None,
1811 1796 )
1812 1797 coreconfigitem(
1813 1798 b'server',
1814 1799 b'bookmarks-pushkey-compat',
1815 1800 default=True,
1816 1801 )
1817 1802 coreconfigitem(
1818 1803 b'server',
1819 1804 b'bundle1',
1820 1805 default=True,
1821 1806 )
1822 1807 coreconfigitem(
1823 1808 b'server',
1824 1809 b'bundle1gd',
1825 1810 default=None,
1826 1811 )
1827 1812 coreconfigitem(
1828 1813 b'server',
1829 1814 b'bundle1.pull',
1830 1815 default=None,
1831 1816 )
1832 1817 coreconfigitem(
1833 1818 b'server',
1834 1819 b'bundle1gd.pull',
1835 1820 default=None,
1836 1821 )
1837 1822 coreconfigitem(
1838 1823 b'server',
1839 1824 b'bundle1.push',
1840 1825 default=None,
1841 1826 )
1842 1827 coreconfigitem(
1843 1828 b'server',
1844 1829 b'bundle1gd.push',
1845 1830 default=None,
1846 1831 )
1847 1832 coreconfigitem(
1848 1833 b'server',
1849 1834 b'bundle2.stream',
1850 1835 default=True,
1851 1836 alias=[(b'experimental', b'bundle2.stream')],
1852 1837 )
1853 1838 coreconfigitem(
1854 1839 b'server',
1855 1840 b'compressionengines',
1856 1841 default=list,
1857 1842 )
1858 1843 coreconfigitem(
1859 1844 b'server',
1860 1845 b'concurrent-push-mode',
1861 1846 default=b'check-related',
1862 1847 )
1863 1848 coreconfigitem(
1864 1849 b'server',
1865 1850 b'disablefullbundle',
1866 1851 default=False,
1867 1852 )
1868 1853 coreconfigitem(
1869 1854 b'server',
1870 1855 b'maxhttpheaderlen',
1871 1856 default=1024,
1872 1857 )
1873 1858 coreconfigitem(
1874 1859 b'server',
1875 1860 b'pullbundle',
1876 1861 default=False,
1877 1862 )
1878 1863 coreconfigitem(
1879 1864 b'server',
1880 1865 b'preferuncompressed',
1881 1866 default=False,
1882 1867 )
1883 1868 coreconfigitem(
1884 1869 b'server',
1885 1870 b'streamunbundle',
1886 1871 default=False,
1887 1872 )
1888 1873 coreconfigitem(
1889 1874 b'server',
1890 1875 b'uncompressed',
1891 1876 default=True,
1892 1877 )
1893 1878 coreconfigitem(
1894 1879 b'server',
1895 1880 b'uncompressedallowsecret',
1896 1881 default=False,
1897 1882 )
1898 1883 coreconfigitem(
1899 1884 b'server',
1900 1885 b'view',
1901 1886 default=b'served',
1902 1887 )
1903 1888 coreconfigitem(
1904 1889 b'server',
1905 1890 b'validate',
1906 1891 default=False,
1907 1892 )
1908 1893 coreconfigitem(
1909 1894 b'server',
1910 1895 b'zliblevel',
1911 1896 default=-1,
1912 1897 )
1913 1898 coreconfigitem(
1914 1899 b'server',
1915 1900 b'zstdlevel',
1916 1901 default=3,
1917 1902 )
1918 1903 coreconfigitem(
1919 1904 b'share',
1920 1905 b'pool',
1921 1906 default=None,
1922 1907 )
1923 1908 coreconfigitem(
1924 1909 b'share',
1925 1910 b'poolnaming',
1926 1911 default=b'identity',
1927 1912 )
1928 1913 coreconfigitem(
1914 b'share',
1915 b'safe-mismatch.source-not-safe',
1916 default=b'abort',
1917 )
1918 coreconfigitem(
1919 b'share',
1920 b'safe-mismatch.source-safe',
1921 default=b'abort',
1922 )
1923 coreconfigitem(
1929 1924 b'shelve',
1930 1925 b'maxbackups',
1931 1926 default=10,
1932 1927 )
1933 1928 coreconfigitem(
1934 1929 b'smtp',
1935 1930 b'host',
1936 1931 default=None,
1937 1932 )
1938 1933 coreconfigitem(
1939 1934 b'smtp',
1940 1935 b'local_hostname',
1941 1936 default=None,
1942 1937 )
1943 1938 coreconfigitem(
1944 1939 b'smtp',
1945 1940 b'password',
1946 1941 default=None,
1947 1942 )
1948 1943 coreconfigitem(
1949 1944 b'smtp',
1950 1945 b'port',
1951 1946 default=dynamicdefault,
1952 1947 )
1953 1948 coreconfigitem(
1954 1949 b'smtp',
1955 1950 b'tls',
1956 1951 default=b'none',
1957 1952 )
1958 1953 coreconfigitem(
1959 1954 b'smtp',
1960 1955 b'username',
1961 1956 default=None,
1962 1957 )
1963 1958 coreconfigitem(
1964 1959 b'sparse',
1965 1960 b'missingwarning',
1966 1961 default=True,
1967 1962 experimental=True,
1968 1963 )
1969 1964 coreconfigitem(
1970 1965 b'subrepos',
1971 1966 b'allowed',
1972 1967 default=dynamicdefault, # to make backporting simpler
1973 1968 )
1974 1969 coreconfigitem(
1975 1970 b'subrepos',
1976 1971 b'hg:allowed',
1977 1972 default=dynamicdefault,
1978 1973 )
1979 1974 coreconfigitem(
1980 1975 b'subrepos',
1981 1976 b'git:allowed',
1982 1977 default=dynamicdefault,
1983 1978 )
1984 1979 coreconfigitem(
1985 1980 b'subrepos',
1986 1981 b'svn:allowed',
1987 1982 default=dynamicdefault,
1988 1983 )
1989 1984 coreconfigitem(
1990 1985 b'templates',
1991 1986 b'.*',
1992 1987 default=None,
1993 1988 generic=True,
1994 1989 )
1995 1990 coreconfigitem(
1996 1991 b'templateconfig',
1997 1992 b'.*',
1998 1993 default=dynamicdefault,
1999 1994 generic=True,
2000 1995 )
2001 1996 coreconfigitem(
2002 1997 b'trusted',
2003 1998 b'groups',
2004 1999 default=list,
2005 2000 )
2006 2001 coreconfigitem(
2007 2002 b'trusted',
2008 2003 b'users',
2009 2004 default=list,
2010 2005 )
2011 2006 coreconfigitem(
2012 2007 b'ui',
2013 2008 b'_usedassubrepo',
2014 2009 default=False,
2015 2010 )
2016 2011 coreconfigitem(
2017 2012 b'ui',
2018 2013 b'allowemptycommit',
2019 2014 default=False,
2020 2015 )
2021 2016 coreconfigitem(
2022 2017 b'ui',
2023 2018 b'archivemeta',
2024 2019 default=True,
2025 2020 )
2026 2021 coreconfigitem(
2027 2022 b'ui',
2028 2023 b'askusername',
2029 2024 default=False,
2030 2025 )
2031 2026 coreconfigitem(
2032 2027 b'ui',
2033 2028 b'available-memory',
2034 2029 default=None,
2035 2030 )
2036 2031
2037 2032 coreconfigitem(
2038 2033 b'ui',
2039 2034 b'clonebundlefallback',
2040 2035 default=False,
2041 2036 )
2042 2037 coreconfigitem(
2043 2038 b'ui',
2044 2039 b'clonebundleprefers',
2045 2040 default=list,
2046 2041 )
2047 2042 coreconfigitem(
2048 2043 b'ui',
2049 2044 b'clonebundles',
2050 2045 default=True,
2051 2046 )
2052 2047 coreconfigitem(
2053 2048 b'ui',
2054 2049 b'color',
2055 2050 default=b'auto',
2056 2051 )
2057 2052 coreconfigitem(
2058 2053 b'ui',
2059 2054 b'commitsubrepos',
2060 2055 default=False,
2061 2056 )
2062 2057 coreconfigitem(
2063 2058 b'ui',
2064 2059 b'debug',
2065 2060 default=False,
2066 2061 )
2067 2062 coreconfigitem(
2068 2063 b'ui',
2069 2064 b'debugger',
2070 2065 default=None,
2071 2066 )
2072 2067 coreconfigitem(
2073 2068 b'ui',
2074 2069 b'editor',
2075 2070 default=dynamicdefault,
2076 2071 )
2077 2072 coreconfigitem(
2078 2073 b'ui',
2079 2074 b'detailed-exit-code',
2080 2075 default=False,
2081 2076 experimental=True,
2082 2077 )
2083 2078 coreconfigitem(
2084 2079 b'ui',
2085 2080 b'fallbackencoding',
2086 2081 default=None,
2087 2082 )
2088 2083 coreconfigitem(
2089 2084 b'ui',
2090 2085 b'forcecwd',
2091 2086 default=None,
2092 2087 )
2093 2088 coreconfigitem(
2094 2089 b'ui',
2095 2090 b'forcemerge',
2096 2091 default=None,
2097 2092 )
2098 2093 coreconfigitem(
2099 2094 b'ui',
2100 2095 b'formatdebug',
2101 2096 default=False,
2102 2097 )
2103 2098 coreconfigitem(
2104 2099 b'ui',
2105 2100 b'formatjson',
2106 2101 default=False,
2107 2102 )
2108 2103 coreconfigitem(
2109 2104 b'ui',
2110 2105 b'formatted',
2111 2106 default=None,
2112 2107 )
2113 2108 coreconfigitem(
2114 2109 b'ui',
2115 2110 b'interactive',
2116 2111 default=None,
2117 2112 )
2118 2113 coreconfigitem(
2119 2114 b'ui',
2120 2115 b'interface',
2121 2116 default=None,
2122 2117 )
2123 2118 coreconfigitem(
2124 2119 b'ui',
2125 2120 b'interface.chunkselector',
2126 2121 default=None,
2127 2122 )
2128 2123 coreconfigitem(
2129 2124 b'ui',
2130 2125 b'large-file-limit',
2131 2126 default=10000000,
2132 2127 )
2133 2128 coreconfigitem(
2134 2129 b'ui',
2135 2130 b'logblockedtimes',
2136 2131 default=False,
2137 2132 )
2138 2133 coreconfigitem(
2139 2134 b'ui',
2140 2135 b'merge',
2141 2136 default=None,
2142 2137 )
2143 2138 coreconfigitem(
2144 2139 b'ui',
2145 2140 b'mergemarkers',
2146 2141 default=b'basic',
2147 2142 )
2148 2143 coreconfigitem(
2149 2144 b'ui',
2150 2145 b'message-output',
2151 2146 default=b'stdio',
2152 2147 )
2153 2148 coreconfigitem(
2154 2149 b'ui',
2155 2150 b'nontty',
2156 2151 default=False,
2157 2152 )
2158 2153 coreconfigitem(
2159 2154 b'ui',
2160 2155 b'origbackuppath',
2161 2156 default=None,
2162 2157 )
2163 2158 coreconfigitem(
2164 2159 b'ui',
2165 2160 b'paginate',
2166 2161 default=True,
2167 2162 )
2168 2163 coreconfigitem(
2169 2164 b'ui',
2170 2165 b'patch',
2171 2166 default=None,
2172 2167 )
2173 2168 coreconfigitem(
2174 2169 b'ui',
2175 2170 b'portablefilenames',
2176 2171 default=b'warn',
2177 2172 )
2178 2173 coreconfigitem(
2179 2174 b'ui',
2180 2175 b'promptecho',
2181 2176 default=False,
2182 2177 )
2183 2178 coreconfigitem(
2184 2179 b'ui',
2185 2180 b'quiet',
2186 2181 default=False,
2187 2182 )
2188 2183 coreconfigitem(
2189 2184 b'ui',
2190 2185 b'quietbookmarkmove',
2191 2186 default=False,
2192 2187 )
2193 2188 coreconfigitem(
2194 2189 b'ui',
2195 2190 b'relative-paths',
2196 2191 default=b'legacy',
2197 2192 )
2198 2193 coreconfigitem(
2199 2194 b'ui',
2200 2195 b'remotecmd',
2201 2196 default=b'hg',
2202 2197 )
2203 2198 coreconfigitem(
2204 2199 b'ui',
2205 2200 b'report_untrusted',
2206 2201 default=True,
2207 2202 )
2208 2203 coreconfigitem(
2209 2204 b'ui',
2210 2205 b'rollback',
2211 2206 default=True,
2212 2207 )
2213 2208 coreconfigitem(
2214 2209 b'ui',
2215 2210 b'signal-safe-lock',
2216 2211 default=True,
2217 2212 )
2218 2213 coreconfigitem(
2219 2214 b'ui',
2220 2215 b'slash',
2221 2216 default=False,
2222 2217 )
2223 2218 coreconfigitem(
2224 2219 b'ui',
2225 2220 b'ssh',
2226 2221 default=b'ssh',
2227 2222 )
2228 2223 coreconfigitem(
2229 2224 b'ui',
2230 2225 b'ssherrorhint',
2231 2226 default=None,
2232 2227 )
2233 2228 coreconfigitem(
2234 2229 b'ui',
2235 2230 b'statuscopies',
2236 2231 default=False,
2237 2232 )
2238 2233 coreconfigitem(
2239 2234 b'ui',
2240 2235 b'strict',
2241 2236 default=False,
2242 2237 )
2243 2238 coreconfigitem(
2244 2239 b'ui',
2245 2240 b'style',
2246 2241 default=b'',
2247 2242 )
2248 2243 coreconfigitem(
2249 2244 b'ui',
2250 2245 b'supportcontact',
2251 2246 default=None,
2252 2247 )
2253 2248 coreconfigitem(
2254 2249 b'ui',
2255 2250 b'textwidth',
2256 2251 default=78,
2257 2252 )
2258 2253 coreconfigitem(
2259 2254 b'ui',
2260 2255 b'timeout',
2261 2256 default=b'600',
2262 2257 )
2263 2258 coreconfigitem(
2264 2259 b'ui',
2265 2260 b'timeout.warn',
2266 2261 default=0,
2267 2262 )
2268 2263 coreconfigitem(
2269 2264 b'ui',
2270 2265 b'timestamp-output',
2271 2266 default=False,
2272 2267 )
2273 2268 coreconfigitem(
2274 2269 b'ui',
2275 2270 b'traceback',
2276 2271 default=False,
2277 2272 )
2278 2273 coreconfigitem(
2279 2274 b'ui',
2280 2275 b'tweakdefaults',
2281 2276 default=False,
2282 2277 )
2283 2278 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2284 2279 coreconfigitem(
2285 2280 b'ui',
2286 2281 b'verbose',
2287 2282 default=False,
2288 2283 )
2289 2284 coreconfigitem(
2290 2285 b'verify',
2291 2286 b'skipflags',
2292 2287 default=None,
2293 2288 )
2294 2289 coreconfigitem(
2295 2290 b'web',
2296 2291 b'allowbz2',
2297 2292 default=False,
2298 2293 )
2299 2294 coreconfigitem(
2300 2295 b'web',
2301 2296 b'allowgz',
2302 2297 default=False,
2303 2298 )
2304 2299 coreconfigitem(
2305 2300 b'web',
2306 2301 b'allow-pull',
2307 2302 alias=[(b'web', b'allowpull')],
2308 2303 default=True,
2309 2304 )
2310 2305 coreconfigitem(
2311 2306 b'web',
2312 2307 b'allow-push',
2313 2308 alias=[(b'web', b'allow_push')],
2314 2309 default=list,
2315 2310 )
2316 2311 coreconfigitem(
2317 2312 b'web',
2318 2313 b'allowzip',
2319 2314 default=False,
2320 2315 )
2321 2316 coreconfigitem(
2322 2317 b'web',
2323 2318 b'archivesubrepos',
2324 2319 default=False,
2325 2320 )
2326 2321 coreconfigitem(
2327 2322 b'web',
2328 2323 b'cache',
2329 2324 default=True,
2330 2325 )
2331 2326 coreconfigitem(
2332 2327 b'web',
2333 2328 b'comparisoncontext',
2334 2329 default=5,
2335 2330 )
2336 2331 coreconfigitem(
2337 2332 b'web',
2338 2333 b'contact',
2339 2334 default=None,
2340 2335 )
2341 2336 coreconfigitem(
2342 2337 b'web',
2343 2338 b'deny_push',
2344 2339 default=list,
2345 2340 )
2346 2341 coreconfigitem(
2347 2342 b'web',
2348 2343 b'guessmime',
2349 2344 default=False,
2350 2345 )
2351 2346 coreconfigitem(
2352 2347 b'web',
2353 2348 b'hidden',
2354 2349 default=False,
2355 2350 )
2356 2351 coreconfigitem(
2357 2352 b'web',
2358 2353 b'labels',
2359 2354 default=list,
2360 2355 )
2361 2356 coreconfigitem(
2362 2357 b'web',
2363 2358 b'logoimg',
2364 2359 default=b'hglogo.png',
2365 2360 )
2366 2361 coreconfigitem(
2367 2362 b'web',
2368 2363 b'logourl',
2369 2364 default=b'https://mercurial-scm.org/',
2370 2365 )
2371 2366 coreconfigitem(
2372 2367 b'web',
2373 2368 b'accesslog',
2374 2369 default=b'-',
2375 2370 )
2376 2371 coreconfigitem(
2377 2372 b'web',
2378 2373 b'address',
2379 2374 default=b'',
2380 2375 )
2381 2376 coreconfigitem(
2382 2377 b'web',
2383 2378 b'allow-archive',
2384 2379 alias=[(b'web', b'allow_archive')],
2385 2380 default=list,
2386 2381 )
2387 2382 coreconfigitem(
2388 2383 b'web',
2389 2384 b'allow_read',
2390 2385 default=list,
2391 2386 )
2392 2387 coreconfigitem(
2393 2388 b'web',
2394 2389 b'baseurl',
2395 2390 default=None,
2396 2391 )
2397 2392 coreconfigitem(
2398 2393 b'web',
2399 2394 b'cacerts',
2400 2395 default=None,
2401 2396 )
2402 2397 coreconfigitem(
2403 2398 b'web',
2404 2399 b'certificate',
2405 2400 default=None,
2406 2401 )
2407 2402 coreconfigitem(
2408 2403 b'web',
2409 2404 b'collapse',
2410 2405 default=False,
2411 2406 )
2412 2407 coreconfigitem(
2413 2408 b'web',
2414 2409 b'csp',
2415 2410 default=None,
2416 2411 )
2417 2412 coreconfigitem(
2418 2413 b'web',
2419 2414 b'deny_read',
2420 2415 default=list,
2421 2416 )
2422 2417 coreconfigitem(
2423 2418 b'web',
2424 2419 b'descend',
2425 2420 default=True,
2426 2421 )
2427 2422 coreconfigitem(
2428 2423 b'web',
2429 2424 b'description',
2430 2425 default=b"",
2431 2426 )
2432 2427 coreconfigitem(
2433 2428 b'web',
2434 2429 b'encoding',
2435 2430 default=lambda: encoding.encoding,
2436 2431 )
2437 2432 coreconfigitem(
2438 2433 b'web',
2439 2434 b'errorlog',
2440 2435 default=b'-',
2441 2436 )
2442 2437 coreconfigitem(
2443 2438 b'web',
2444 2439 b'ipv6',
2445 2440 default=False,
2446 2441 )
2447 2442 coreconfigitem(
2448 2443 b'web',
2449 2444 b'maxchanges',
2450 2445 default=10,
2451 2446 )
2452 2447 coreconfigitem(
2453 2448 b'web',
2454 2449 b'maxfiles',
2455 2450 default=10,
2456 2451 )
2457 2452 coreconfigitem(
2458 2453 b'web',
2459 2454 b'maxshortchanges',
2460 2455 default=60,
2461 2456 )
2462 2457 coreconfigitem(
2463 2458 b'web',
2464 2459 b'motd',
2465 2460 default=b'',
2466 2461 )
2467 2462 coreconfigitem(
2468 2463 b'web',
2469 2464 b'name',
2470 2465 default=dynamicdefault,
2471 2466 )
2472 2467 coreconfigitem(
2473 2468 b'web',
2474 2469 b'port',
2475 2470 default=8000,
2476 2471 )
2477 2472 coreconfigitem(
2478 2473 b'web',
2479 2474 b'prefix',
2480 2475 default=b'',
2481 2476 )
2482 2477 coreconfigitem(
2483 2478 b'web',
2484 2479 b'push_ssl',
2485 2480 default=True,
2486 2481 )
2487 2482 coreconfigitem(
2488 2483 b'web',
2489 2484 b'refreshinterval',
2490 2485 default=20,
2491 2486 )
2492 2487 coreconfigitem(
2493 2488 b'web',
2494 2489 b'server-header',
2495 2490 default=None,
2496 2491 )
2497 2492 coreconfigitem(
2498 2493 b'web',
2499 2494 b'static',
2500 2495 default=None,
2501 2496 )
2502 2497 coreconfigitem(
2503 2498 b'web',
2504 2499 b'staticurl',
2505 2500 default=None,
2506 2501 )
2507 2502 coreconfigitem(
2508 2503 b'web',
2509 2504 b'stripes',
2510 2505 default=1,
2511 2506 )
2512 2507 coreconfigitem(
2513 2508 b'web',
2514 2509 b'style',
2515 2510 default=b'paper',
2516 2511 )
2517 2512 coreconfigitem(
2518 2513 b'web',
2519 2514 b'templates',
2520 2515 default=None,
2521 2516 )
2522 2517 coreconfigitem(
2523 2518 b'web',
2524 2519 b'view',
2525 2520 default=b'served',
2526 2521 experimental=True,
2527 2522 )
2528 2523 coreconfigitem(
2529 2524 b'worker',
2530 2525 b'backgroundclose',
2531 2526 default=dynamicdefault,
2532 2527 )
2533 2528 # Windows defaults to a limit of 512 open files. A buffer of 128
2534 2529 # should give us enough headway.
2535 2530 coreconfigitem(
2536 2531 b'worker',
2537 2532 b'backgroundclosemaxqueue',
2538 2533 default=384,
2539 2534 )
2540 2535 coreconfigitem(
2541 2536 b'worker',
2542 2537 b'backgroundcloseminfilecount',
2543 2538 default=2048,
2544 2539 )
2545 2540 coreconfigitem(
2546 2541 b'worker',
2547 2542 b'backgroundclosethreadcount',
2548 2543 default=4,
2549 2544 )
2550 2545 coreconfigitem(
2551 2546 b'worker',
2552 2547 b'enabled',
2553 2548 default=True,
2554 2549 )
2555 2550 coreconfigitem(
2556 2551 b'worker',
2557 2552 b'numcpus',
2558 2553 default=None,
2559 2554 )
2560 2555
2561 2556 # Rebase related configuration moved to core because other extension are doing
2562 2557 # strange things. For example, shelve import the extensions to reuse some bit
2563 2558 # without formally loading it.
2564 2559 coreconfigitem(
2565 2560 b'commands',
2566 2561 b'rebase.requiredest',
2567 2562 default=False,
2568 2563 )
2569 2564 coreconfigitem(
2570 2565 b'experimental',
2571 2566 b'rebaseskipobsolete',
2572 2567 default=True,
2573 2568 )
2574 2569 coreconfigitem(
2575 2570 b'rebase',
2576 2571 b'singletransaction',
2577 2572 default=False,
2578 2573 )
2579 2574 coreconfigitem(
2580 2575 b'rebase',
2581 2576 b'experimental.inmemory',
2582 2577 default=False,
2583 2578 )
@@ -1,2988 +1,3021 b''
1 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 Troubleshooting
5 5 ===============
6 6
7 7 If you're having problems with your configuration,
8 8 :hg:`config --debug` can help you understand what is introducing
9 9 a setting into your environment.
10 10
11 11 See :hg:`help config.syntax` and :hg:`help config.files`
12 12 for information about how and where to override things.
13 13
14 14 Structure
15 15 =========
16 16
17 17 The configuration files use a simple ini-file format. A configuration
18 18 file consists of sections, led by a ``[section]`` header and followed
19 19 by ``name = value`` entries::
20 20
21 21 [ui]
22 22 username = Firstname Lastname <firstname.lastname@example.net>
23 23 verbose = True
24 24
25 25 The above entries will be referred to as ``ui.username`` and
26 26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27 27
28 28 Files
29 29 =====
30 30
31 31 Mercurial reads configuration data from several files, if they exist.
32 32 These files do not exist by default and you will have to create the
33 33 appropriate configuration files yourself:
34 34
35 35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36 36
37 37 Global configuration like the username setting is typically put into:
38 38
39 39 .. container:: windows
40 40
41 41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42 42
43 43 .. container:: unix.plan9
44 44
45 45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46 46
47 47 The names of these files depend on the system on which Mercurial is
48 48 installed. ``*.rc`` files from a single directory are read in
49 49 alphabetical order, later ones overriding earlier ones. Where multiple
50 50 paths are given below, settings from earlier paths override later
51 51 ones.
52 52
53 53 .. container:: verbose.unix
54 54
55 55 On Unix, the following files are consulted:
56 56
57 57 - ``<repo>/.hg/hgrc-not-shared`` (per-repository)
58 58 - ``<repo>/.hg/hgrc`` (per-repository)
59 59 - ``$HOME/.hgrc`` (per-user)
60 60 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
61 61 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
62 62 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
63 63 - ``/etc/mercurial/hgrc`` (per-system)
64 64 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
65 65 - ``<internal>/*.rc`` (defaults)
66 66
67 67 .. container:: verbose.windows
68 68
69 69 On Windows, the following files are consulted:
70 70
71 71 - ``<repo>/.hg/hgrc-not-shared`` (per-repository)
72 72 - ``<repo>/.hg/hgrc`` (per-repository)
73 73 - ``%USERPROFILE%\.hgrc`` (per-user)
74 74 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
75 75 - ``%HOME%\.hgrc`` (per-user)
76 76 - ``%HOME%\Mercurial.ini`` (per-user)
77 77 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-system)
78 78 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
79 79 - ``<install-dir>\Mercurial.ini`` (per-installation)
80 80 - ``%PROGRAMDATA%\Mercurial\hgrc`` (per-system)
81 81 - ``%PROGRAMDATA%\Mercurial\Mercurial.ini`` (per-system)
82 82 - ``%PROGRAMDATA%\Mercurial\hgrc.d\*.rc`` (per-system)
83 83 - ``<internal>/*.rc`` (defaults)
84 84
85 85 .. note::
86 86
87 87 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
88 88 is used when running 32-bit Python on 64-bit Windows.
89 89
90 90 .. container:: verbose.plan9
91 91
92 92 On Plan9, the following files are consulted:
93 93
94 94 - ``<repo>/.hg/hgrc-not-shared`` (per-repository)
95 95 - ``<repo>/.hg/hgrc`` (per-repository)
96 96 - ``$home/lib/hgrc`` (per-user)
97 97 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
98 98 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
99 99 - ``/lib/mercurial/hgrc`` (per-system)
100 100 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
101 101 - ``<internal>/*.rc`` (defaults)
102 102
103 103 Per-repository configuration options only apply in a
104 104 particular repository. This file is not version-controlled, and
105 105 will not get transferred during a "clone" operation. Options in
106 106 this file override options in all other configuration files.
107 107
108 108 .. container:: unix.plan9
109 109
110 110 On Plan 9 and Unix, most of this file will be ignored if it doesn't
111 111 belong to a trusted user or to a trusted group. See
112 112 :hg:`help config.trusted` for more details.
113 113
114 114 Per-user configuration file(s) are for the user running Mercurial. Options
115 115 in these files apply to all Mercurial commands executed by this user in any
116 116 directory. Options in these files override per-system and per-installation
117 117 options.
118 118
119 119 Per-installation configuration files are searched for in the
120 120 directory where Mercurial is installed. ``<install-root>`` is the
121 121 parent directory of the **hg** executable (or symlink) being run.
122 122
123 123 .. container:: unix.plan9
124 124
125 125 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
126 126 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
127 127 files apply to all Mercurial commands executed by any user in any
128 128 directory.
129 129
130 130 Per-installation configuration files are for the system on
131 131 which Mercurial is running. Options in these files apply to all
132 132 Mercurial commands executed by any user in any directory. Registry
133 133 keys contain PATH-like strings, every part of which must reference
134 134 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
135 135 be read. Mercurial checks each of these locations in the specified
136 136 order until one or more configuration files are detected.
137 137
138 138 Per-system configuration files are for the system on which Mercurial
139 139 is running. Options in these files apply to all Mercurial commands
140 140 executed by any user in any directory. Options in these files
141 141 override per-installation options.
142 142
143 143 Mercurial comes with some default configuration. The default configuration
144 144 files are installed with Mercurial and will be overwritten on upgrades. Default
145 145 configuration files should never be edited by users or administrators but can
146 146 be overridden in other configuration files. So far the directory only contains
147 147 merge tool configuration but packagers can also put other default configuration
148 148 there.
149 149
150 150 .. container:: verbose
151 151
152 152 On versions 5.7 and later, if share-safe functionality is enabled,
153 153 shares will read config file of share source too.
154 154 `<share-source/.hg/hgrc>` is read before reading `<repo/.hg/hgrc>`.
155 155
156 156 For configs which should not be shared, `<repo/.hg/hgrc-not-shared>`
157 157 should be used.
158 158
159 159 Syntax
160 160 ======
161 161
162 162 A configuration file consists of sections, led by a ``[section]`` header
163 163 and followed by ``name = value`` entries (sometimes called
164 164 ``configuration keys``)::
165 165
166 166 [spam]
167 167 eggs=ham
168 168 green=
169 169 eggs
170 170
171 171 Each line contains one entry. If the lines that follow are indented,
172 172 they are treated as continuations of that entry. Leading whitespace is
173 173 removed from values. Empty lines are skipped. Lines beginning with
174 174 ``#`` or ``;`` are ignored and may be used to provide comments.
175 175
176 176 Configuration keys can be set multiple times, in which case Mercurial
177 177 will use the value that was configured last. As an example::
178 178
179 179 [spam]
180 180 eggs=large
181 181 ham=serrano
182 182 eggs=small
183 183
184 184 This would set the configuration key named ``eggs`` to ``small``.
185 185
186 186 It is also possible to define a section multiple times. A section can
187 187 be redefined on the same and/or on different configuration files. For
188 188 example::
189 189
190 190 [foo]
191 191 eggs=large
192 192 ham=serrano
193 193 eggs=small
194 194
195 195 [bar]
196 196 eggs=ham
197 197 green=
198 198 eggs
199 199
200 200 [foo]
201 201 ham=prosciutto
202 202 eggs=medium
203 203 bread=toasted
204 204
205 205 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
206 206 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
207 207 respectively. As you can see there only thing that matters is the last
208 208 value that was set for each of the configuration keys.
209 209
210 210 If a configuration key is set multiple times in different
211 211 configuration files the final value will depend on the order in which
212 212 the different configuration files are read, with settings from earlier
213 213 paths overriding later ones as described on the ``Files`` section
214 214 above.
215 215
216 216 A line of the form ``%include file`` will include ``file`` into the
217 217 current configuration file. The inclusion is recursive, which means
218 218 that included files can include other files. Filenames are relative to
219 219 the configuration file in which the ``%include`` directive is found.
220 220 Environment variables and ``~user`` constructs are expanded in
221 221 ``file``. This lets you do something like::
222 222
223 223 %include ~/.hgrc.d/$HOST.rc
224 224
225 225 to include a different configuration file on each computer you use.
226 226
227 227 A line with ``%unset name`` will remove ``name`` from the current
228 228 section, if it has been set previously.
229 229
230 230 The values are either free-form text strings, lists of text strings,
231 231 or Boolean values. Boolean values can be set to true using any of "1",
232 232 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
233 233 (all case insensitive).
234 234
235 235 List values are separated by whitespace or comma, except when values are
236 236 placed in double quotation marks::
237 237
238 238 allow_read = "John Doe, PhD", brian, betty
239 239
240 240 Quotation marks can be escaped by prefixing them with a backslash. Only
241 241 quotation marks at the beginning of a word is counted as a quotation
242 242 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
243 243
244 244 Sections
245 245 ========
246 246
247 247 This section describes the different sections that may appear in a
248 248 Mercurial configuration file, the purpose of each section, its possible
249 249 keys, and their possible values.
250 250
251 251 ``alias``
252 252 ---------
253 253
254 254 Defines command aliases.
255 255
256 256 Aliases allow you to define your own commands in terms of other
257 257 commands (or aliases), optionally including arguments. Positional
258 258 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
259 259 are expanded by Mercurial before execution. Positional arguments not
260 260 already used by ``$N`` in the definition are put at the end of the
261 261 command to be executed.
262 262
263 263 Alias definitions consist of lines of the form::
264 264
265 265 <alias> = <command> [<argument>]...
266 266
267 267 For example, this definition::
268 268
269 269 latest = log --limit 5
270 270
271 271 creates a new command ``latest`` that shows only the five most recent
272 272 changesets. You can define subsequent aliases using earlier ones::
273 273
274 274 stable5 = latest -b stable
275 275
276 276 .. note::
277 277
278 278 It is possible to create aliases with the same names as
279 279 existing commands, which will then override the original
280 280 definitions. This is almost always a bad idea!
281 281
282 282 An alias can start with an exclamation point (``!``) to make it a
283 283 shell alias. A shell alias is executed with the shell and will let you
284 284 run arbitrary commands. As an example, ::
285 285
286 286 echo = !echo $@
287 287
288 288 will let you do ``hg echo foo`` to have ``foo`` printed in your
289 289 terminal. A better example might be::
290 290
291 291 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
292 292
293 293 which will make ``hg purge`` delete all unknown files in the
294 294 repository in the same manner as the purge extension.
295 295
296 296 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
297 297 expand to the command arguments. Unmatched arguments are
298 298 removed. ``$0`` expands to the alias name and ``$@`` expands to all
299 299 arguments separated by a space. ``"$@"`` (with quotes) expands to all
300 300 arguments quoted individually and separated by a space. These expansions
301 301 happen before the command is passed to the shell.
302 302
303 303 Shell aliases are executed in an environment where ``$HG`` expands to
304 304 the path of the Mercurial that was used to execute the alias. This is
305 305 useful when you want to call further Mercurial commands in a shell
306 306 alias, as was done above for the purge alias. In addition,
307 307 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
308 308 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
309 309
310 310 .. note::
311 311
312 312 Some global configuration options such as ``-R`` are
313 313 processed before shell aliases and will thus not be passed to
314 314 aliases.
315 315
316 316
317 317 ``annotate``
318 318 ------------
319 319
320 320 Settings used when displaying file annotations. All values are
321 321 Booleans and default to False. See :hg:`help config.diff` for
322 322 related options for the diff command.
323 323
324 324 ``ignorews``
325 325 Ignore white space when comparing lines.
326 326
327 327 ``ignorewseol``
328 328 Ignore white space at the end of a line when comparing lines.
329 329
330 330 ``ignorewsamount``
331 331 Ignore changes in the amount of white space.
332 332
333 333 ``ignoreblanklines``
334 334 Ignore changes whose lines are all blank.
335 335
336 336
337 337 ``auth``
338 338 --------
339 339
340 340 Authentication credentials and other authentication-like configuration
341 341 for HTTP connections. This section allows you to store usernames and
342 342 passwords for use when logging *into* HTTP servers. See
343 343 :hg:`help config.web` if you want to configure *who* can login to
344 344 your HTTP server.
345 345
346 346 The following options apply to all hosts.
347 347
348 348 ``cookiefile``
349 349 Path to a file containing HTTP cookie lines. Cookies matching a
350 350 host will be sent automatically.
351 351
352 352 The file format uses the Mozilla cookies.txt format, which defines cookies
353 353 on their own lines. Each line contains 7 fields delimited by the tab
354 354 character (domain, is_domain_cookie, path, is_secure, expires, name,
355 355 value). For more info, do an Internet search for "Netscape cookies.txt
356 356 format."
357 357
358 358 Note: the cookies parser does not handle port numbers on domains. You
359 359 will need to remove ports from the domain for the cookie to be recognized.
360 360 This could result in a cookie being disclosed to an unwanted server.
361 361
362 362 The cookies file is read-only.
363 363
364 364 Other options in this section are grouped by name and have the following
365 365 format::
366 366
367 367 <name>.<argument> = <value>
368 368
369 369 where ``<name>`` is used to group arguments into authentication
370 370 entries. Example::
371 371
372 372 foo.prefix = hg.intevation.de/mercurial
373 373 foo.username = foo
374 374 foo.password = bar
375 375 foo.schemes = http https
376 376
377 377 bar.prefix = secure.example.org
378 378 bar.key = path/to/file.key
379 379 bar.cert = path/to/file.cert
380 380 bar.schemes = https
381 381
382 382 Supported arguments:
383 383
384 384 ``prefix``
385 385 Either ``*`` or a URI prefix with or without the scheme part.
386 386 The authentication entry with the longest matching prefix is used
387 387 (where ``*`` matches everything and counts as a match of length
388 388 1). If the prefix doesn't include a scheme, the match is performed
389 389 against the URI with its scheme stripped as well, and the schemes
390 390 argument, q.v., is then subsequently consulted.
391 391
392 392 ``username``
393 393 Optional. Username to authenticate with. If not given, and the
394 394 remote site requires basic or digest authentication, the user will
395 395 be prompted for it. Environment variables are expanded in the
396 396 username letting you do ``foo.username = $USER``. If the URI
397 397 includes a username, only ``[auth]`` entries with a matching
398 398 username or without a username will be considered.
399 399
400 400 ``password``
401 401 Optional. Password to authenticate with. If not given, and the
402 402 remote site requires basic or digest authentication, the user
403 403 will be prompted for it.
404 404
405 405 ``key``
406 406 Optional. PEM encoded client certificate key file. Environment
407 407 variables are expanded in the filename.
408 408
409 409 ``cert``
410 410 Optional. PEM encoded client certificate chain file. Environment
411 411 variables are expanded in the filename.
412 412
413 413 ``schemes``
414 414 Optional. Space separated list of URI schemes to use this
415 415 authentication entry with. Only used if the prefix doesn't include
416 416 a scheme. Supported schemes are http and https. They will match
417 417 static-http and static-https respectively, as well.
418 418 (default: https)
419 419
420 420 If no suitable authentication entry is found, the user is prompted
421 421 for credentials as usual if required by the remote.
422 422
423 423 ``cmdserver``
424 424 -------------
425 425
426 426 Controls command server settings. (ADVANCED)
427 427
428 428 ``message-encodings``
429 429 List of encodings for the ``m`` (message) channel. The first encoding
430 430 supported by the server will be selected and advertised in the hello
431 431 message. This is useful only when ``ui.message-output`` is set to
432 432 ``channel``. Supported encodings are ``cbor``.
433 433
434 434 ``shutdown-on-interrupt``
435 435 If set to false, the server's main loop will continue running after
436 436 SIGINT received. ``runcommand`` requests can still be interrupted by
437 437 SIGINT. Close the write end of the pipe to shut down the server
438 438 process gracefully.
439 439 (default: True)
440 440
441 441 ``color``
442 442 ---------
443 443
444 444 Configure the Mercurial color mode. For details about how to define your custom
445 445 effect and style see :hg:`help color`.
446 446
447 447 ``mode``
448 448 String: control the method used to output color. One of ``auto``, ``ansi``,
449 449 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
450 450 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
451 451 terminal. Any invalid value will disable color.
452 452
453 453 ``pagermode``
454 454 String: optional override of ``color.mode`` used with pager.
455 455
456 456 On some systems, terminfo mode may cause problems when using
457 457 color with ``less -R`` as a pager program. less with the -R option
458 458 will only display ECMA-48 color codes, and terminfo mode may sometimes
459 459 emit codes that less doesn't understand. You can work around this by
460 460 either using ansi mode (or auto mode), or by using less -r (which will
461 461 pass through all terminal control codes, not just color control
462 462 codes).
463 463
464 464 On some systems (such as MSYS in Windows), the terminal may support
465 465 a different color mode than the pager program.
466 466
467 467 ``commands``
468 468 ------------
469 469
470 470 ``commit.post-status``
471 471 Show status of files in the working directory after successful commit.
472 472 (default: False)
473 473
474 474 ``merge.require-rev``
475 475 Require that the revision to merge the current commit with be specified on
476 476 the command line. If this is enabled and a revision is not specified, the
477 477 command aborts.
478 478 (default: False)
479 479
480 480 ``push.require-revs``
481 481 Require revisions to push be specified using one or more mechanisms such as
482 482 specifying them positionally on the command line, using ``-r``, ``-b``,
483 483 and/or ``-B`` on the command line, or using ``paths.<path>:pushrev`` in the
484 484 configuration. If this is enabled and revisions are not specified, the
485 485 command aborts.
486 486 (default: False)
487 487
488 488 ``resolve.confirm``
489 489 Confirm before performing action if no filename is passed.
490 490 (default: False)
491 491
492 492 ``resolve.explicit-re-merge``
493 493 Require uses of ``hg resolve`` to specify which action it should perform,
494 494 instead of re-merging files by default.
495 495 (default: False)
496 496
497 497 ``resolve.mark-check``
498 498 Determines what level of checking :hg:`resolve --mark` will perform before
499 499 marking files as resolved. Valid values are ``none`, ``warn``, and
500 500 ``abort``. ``warn`` will output a warning listing the file(s) that still
501 501 have conflict markers in them, but will still mark everything resolved.
502 502 ``abort`` will output the same warning but will not mark things as resolved.
503 503 If --all is passed and this is set to ``abort``, only a warning will be
504 504 shown (an error will not be raised).
505 505 (default: ``none``)
506 506
507 507 ``status.relative``
508 508 Make paths in :hg:`status` output relative to the current directory.
509 509 (default: False)
510 510
511 511 ``status.terse``
512 512 Default value for the --terse flag, which condenses status output.
513 513 (default: empty)
514 514
515 515 ``update.check``
516 516 Determines what level of checking :hg:`update` will perform before moving
517 517 to a destination revision. Valid values are ``abort``, ``none``,
518 518 ``linear``, and ``noconflict``. ``abort`` always fails if the working
519 519 directory has uncommitted changes. ``none`` performs no checking, and may
520 520 result in a merge with uncommitted changes. ``linear`` allows any update
521 521 as long as it follows a straight line in the revision history, and may
522 522 trigger a merge with uncommitted changes. ``noconflict`` will allow any
523 523 update which would not trigger a merge with uncommitted changes, if any
524 524 are present.
525 525 (default: ``linear``)
526 526
527 527 ``update.requiredest``
528 528 Require that the user pass a destination when running :hg:`update`.
529 529 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
530 530 will be disallowed.
531 531 (default: False)
532 532
533 533 ``committemplate``
534 534 ------------------
535 535
536 536 ``changeset``
537 537 String: configuration in this section is used as the template to
538 538 customize the text shown in the editor when committing.
539 539
540 540 In addition to pre-defined template keywords, commit log specific one
541 541 below can be used for customization:
542 542
543 543 ``extramsg``
544 544 String: Extra message (typically 'Leave message empty to abort
545 545 commit.'). This may be changed by some commands or extensions.
546 546
547 547 For example, the template configuration below shows as same text as
548 548 one shown by default::
549 549
550 550 [committemplate]
551 551 changeset = {desc}\n\n
552 552 HG: Enter commit message. Lines beginning with 'HG:' are removed.
553 553 HG: {extramsg}
554 554 HG: --
555 555 HG: user: {author}\n{ifeq(p2rev, "-1", "",
556 556 "HG: branch merge\n")
557 557 }HG: branch '{branch}'\n{if(activebookmark,
558 558 "HG: bookmark '{activebookmark}'\n") }{subrepos %
559 559 "HG: subrepo {subrepo}\n" }{file_adds %
560 560 "HG: added {file}\n" }{file_mods %
561 561 "HG: changed {file}\n" }{file_dels %
562 562 "HG: removed {file}\n" }{if(files, "",
563 563 "HG: no files changed\n")}
564 564
565 565 ``diff()``
566 566 String: show the diff (see :hg:`help templates` for detail)
567 567
568 568 Sometimes it is helpful to show the diff of the changeset in the editor without
569 569 having to prefix 'HG: ' to each line so that highlighting works correctly. For
570 570 this, Mercurial provides a special string which will ignore everything below
571 571 it::
572 572
573 573 HG: ------------------------ >8 ------------------------
574 574
575 575 For example, the template configuration below will show the diff below the
576 576 extra message::
577 577
578 578 [committemplate]
579 579 changeset = {desc}\n\n
580 580 HG: Enter commit message. Lines beginning with 'HG:' are removed.
581 581 HG: {extramsg}
582 582 HG: ------------------------ >8 ------------------------
583 583 HG: Do not touch the line above.
584 584 HG: Everything below will be removed.
585 585 {diff()}
586 586
587 587 .. note::
588 588
589 589 For some problematic encodings (see :hg:`help win32mbcs` for
590 590 detail), this customization should be configured carefully, to
591 591 avoid showing broken characters.
592 592
593 593 For example, if a multibyte character ending with backslash (0x5c) is
594 594 followed by the ASCII character 'n' in the customized template,
595 595 the sequence of backslash and 'n' is treated as line-feed unexpectedly
596 596 (and the multibyte character is broken, too).
597 597
598 598 Customized template is used for commands below (``--edit`` may be
599 599 required):
600 600
601 601 - :hg:`backout`
602 602 - :hg:`commit`
603 603 - :hg:`fetch` (for merge commit only)
604 604 - :hg:`graft`
605 605 - :hg:`histedit`
606 606 - :hg:`import`
607 607 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
608 608 - :hg:`rebase`
609 609 - :hg:`shelve`
610 610 - :hg:`sign`
611 611 - :hg:`tag`
612 612 - :hg:`transplant`
613 613
614 614 Configuring items below instead of ``changeset`` allows showing
615 615 customized message only for specific actions, or showing different
616 616 messages for each action.
617 617
618 618 - ``changeset.backout`` for :hg:`backout`
619 619 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
620 620 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
621 621 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
622 622 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
623 623 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
624 624 - ``changeset.gpg.sign`` for :hg:`sign`
625 625 - ``changeset.graft`` for :hg:`graft`
626 626 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
627 627 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
628 628 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
629 629 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
630 630 - ``changeset.import.bypass`` for :hg:`import --bypass`
631 631 - ``changeset.import.normal.merge`` for :hg:`import` on merges
632 632 - ``changeset.import.normal.normal`` for :hg:`import` on other
633 633 - ``changeset.mq.qnew`` for :hg:`qnew`
634 634 - ``changeset.mq.qfold`` for :hg:`qfold`
635 635 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
636 636 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
637 637 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
638 638 - ``changeset.rebase.normal`` for :hg:`rebase` on other
639 639 - ``changeset.shelve.shelve`` for :hg:`shelve`
640 640 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
641 641 - ``changeset.tag.remove`` for :hg:`tag --remove`
642 642 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
643 643 - ``changeset.transplant.normal`` for :hg:`transplant` on other
644 644
645 645 These dot-separated lists of names are treated as hierarchical ones.
646 646 For example, ``changeset.tag.remove`` customizes the commit message
647 647 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
648 648 commit message for :hg:`tag` regardless of ``--remove`` option.
649 649
650 650 When the external editor is invoked for a commit, the corresponding
651 651 dot-separated list of names without the ``changeset.`` prefix
652 652 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
653 653 variable.
654 654
655 655 In this section, items other than ``changeset`` can be referred from
656 656 others. For example, the configuration to list committed files up
657 657 below can be referred as ``{listupfiles}``::
658 658
659 659 [committemplate]
660 660 listupfiles = {file_adds %
661 661 "HG: added {file}\n" }{file_mods %
662 662 "HG: changed {file}\n" }{file_dels %
663 663 "HG: removed {file}\n" }{if(files, "",
664 664 "HG: no files changed\n")}
665 665
666 666 ``decode/encode``
667 667 -----------------
668 668
669 669 Filters for transforming files on checkout/checkin. This would
670 670 typically be used for newline processing or other
671 671 localization/canonicalization of files.
672 672
673 673 Filters consist of a filter pattern followed by a filter command.
674 674 Filter patterns are globs by default, rooted at the repository root.
675 675 For example, to match any file ending in ``.txt`` in the root
676 676 directory only, use the pattern ``*.txt``. To match any file ending
677 677 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
678 678 For each file only the first matching filter applies.
679 679
680 680 The filter command can start with a specifier, either ``pipe:`` or
681 681 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
682 682
683 683 A ``pipe:`` command must accept data on stdin and return the transformed
684 684 data on stdout.
685 685
686 686 Pipe example::
687 687
688 688 [encode]
689 689 # uncompress gzip files on checkin to improve delta compression
690 690 # note: not necessarily a good idea, just an example
691 691 *.gz = pipe: gunzip
692 692
693 693 [decode]
694 694 # recompress gzip files when writing them to the working dir (we
695 695 # can safely omit "pipe:", because it's the default)
696 696 *.gz = gzip
697 697
698 698 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
699 699 with the name of a temporary file that contains the data to be
700 700 filtered by the command. The string ``OUTFILE`` is replaced with the name
701 701 of an empty temporary file, where the filtered data must be written by
702 702 the command.
703 703
704 704 .. container:: windows
705 705
706 706 .. note::
707 707
708 708 The tempfile mechanism is recommended for Windows systems,
709 709 where the standard shell I/O redirection operators often have
710 710 strange effects and may corrupt the contents of your files.
711 711
712 712 This filter mechanism is used internally by the ``eol`` extension to
713 713 translate line ending characters between Windows (CRLF) and Unix (LF)
714 714 format. We suggest you use the ``eol`` extension for convenience.
715 715
716 716
717 717 ``defaults``
718 718 ------------
719 719
720 720 (defaults are deprecated. Don't use them. Use aliases instead.)
721 721
722 722 Use the ``[defaults]`` section to define command defaults, i.e. the
723 723 default options/arguments to pass to the specified commands.
724 724
725 725 The following example makes :hg:`log` run in verbose mode, and
726 726 :hg:`status` show only the modified files, by default::
727 727
728 728 [defaults]
729 729 log = -v
730 730 status = -m
731 731
732 732 The actual commands, instead of their aliases, must be used when
733 733 defining command defaults. The command defaults will also be applied
734 734 to the aliases of the commands defined.
735 735
736 736
737 737 ``diff``
738 738 --------
739 739
740 740 Settings used when displaying diffs. Everything except for ``unified``
741 741 is a Boolean and defaults to False. See :hg:`help config.annotate`
742 742 for related options for the annotate command.
743 743
744 744 ``git``
745 745 Use git extended diff format.
746 746
747 747 ``nobinary``
748 748 Omit git binary patches.
749 749
750 750 ``nodates``
751 751 Don't include dates in diff headers.
752 752
753 753 ``noprefix``
754 754 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
755 755
756 756 ``showfunc``
757 757 Show which function each change is in.
758 758
759 759 ``ignorews``
760 760 Ignore white space when comparing lines.
761 761
762 762 ``ignorewsamount``
763 763 Ignore changes in the amount of white space.
764 764
765 765 ``ignoreblanklines``
766 766 Ignore changes whose lines are all blank.
767 767
768 768 ``unified``
769 769 Number of lines of context to show.
770 770
771 771 ``word-diff``
772 772 Highlight changed words.
773 773
774 774 ``email``
775 775 ---------
776 776
777 777 Settings for extensions that send email messages.
778 778
779 779 ``from``
780 780 Optional. Email address to use in "From" header and SMTP envelope
781 781 of outgoing messages.
782 782
783 783 ``to``
784 784 Optional. Comma-separated list of recipients' email addresses.
785 785
786 786 ``cc``
787 787 Optional. Comma-separated list of carbon copy recipients'
788 788 email addresses.
789 789
790 790 ``bcc``
791 791 Optional. Comma-separated list of blind carbon copy recipients'
792 792 email addresses.
793 793
794 794 ``method``
795 795 Optional. Method to use to send email messages. If value is ``smtp``
796 796 (default), use SMTP (see the ``[smtp]`` section for configuration).
797 797 Otherwise, use as name of program to run that acts like sendmail
798 798 (takes ``-f`` option for sender, list of recipients on command line,
799 799 message on stdin). Normally, setting this to ``sendmail`` or
800 800 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
801 801
802 802 ``charsets``
803 803 Optional. Comma-separated list of character sets considered
804 804 convenient for recipients. Addresses, headers, and parts not
805 805 containing patches of outgoing messages will be encoded in the
806 806 first character set to which conversion from local encoding
807 807 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
808 808 conversion fails, the text in question is sent as is.
809 809 (default: '')
810 810
811 811 Order of outgoing email character sets:
812 812
813 813 1. ``us-ascii``: always first, regardless of settings
814 814 2. ``email.charsets``: in order given by user
815 815 3. ``ui.fallbackencoding``: if not in email.charsets
816 816 4. ``$HGENCODING``: if not in email.charsets
817 817 5. ``utf-8``: always last, regardless of settings
818 818
819 819 Email example::
820 820
821 821 [email]
822 822 from = Joseph User <joe.user@example.com>
823 823 method = /usr/sbin/sendmail
824 824 # charsets for western Europeans
825 825 # us-ascii, utf-8 omitted, as they are tried first and last
826 826 charsets = iso-8859-1, iso-8859-15, windows-1252
827 827
828 828
829 829 ``extensions``
830 830 --------------
831 831
832 832 Mercurial has an extension mechanism for adding new features. To
833 833 enable an extension, create an entry for it in this section.
834 834
835 835 If you know that the extension is already in Python's search path,
836 836 you can give the name of the module, followed by ``=``, with nothing
837 837 after the ``=``.
838 838
839 839 Otherwise, give a name that you choose, followed by ``=``, followed by
840 840 the path to the ``.py`` file (including the file name extension) that
841 841 defines the extension.
842 842
843 843 To explicitly disable an extension that is enabled in an hgrc of
844 844 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
845 845 or ``foo = !`` when path is not supplied.
846 846
847 847 Example for ``~/.hgrc``::
848 848
849 849 [extensions]
850 850 # (the churn extension will get loaded from Mercurial's path)
851 851 churn =
852 852 # (this extension will get loaded from the file specified)
853 853 myfeature = ~/.hgext/myfeature.py
854 854
855 855
856 856 ``format``
857 857 ----------
858 858
859 859 Configuration that controls the repository format. Newer format options are more
860 860 powerful, but incompatible with some older versions of Mercurial. Format options
861 861 are considered at repository initialization only. You need to make a new clone
862 862 for config changes to be taken into account.
863 863
864 864 For more details about repository format and version compatibility, see
865 865 https://www.mercurial-scm.org/wiki/MissingRequirement
866 866
867 867 ``usegeneraldelta``
868 868 Enable or disable the "generaldelta" repository format which improves
869 869 repository compression by allowing "revlog" to store deltas against
870 870 arbitrary revisions instead of the previously stored one. This provides
871 871 significant improvement for repositories with branches.
872 872
873 873 Repositories with this on-disk format require Mercurial version 1.9.
874 874
875 875 Enabled by default.
876 876
877 877 ``dotencode``
878 878 Enable or disable the "dotencode" repository format which enhances
879 879 the "fncache" repository format (which has to be enabled to use
880 880 dotencode) to avoid issues with filenames starting with "._" on
881 881 Mac OS X and spaces on Windows.
882 882
883 883 Repositories with this on-disk format require Mercurial version 1.7.
884 884
885 885 Enabled by default.
886 886
887 887 ``usefncache``
888 888 Enable or disable the "fncache" repository format which enhances
889 889 the "store" repository format (which has to be enabled to use
890 890 fncache) to allow longer filenames and avoids using Windows
891 891 reserved names, e.g. "nul".
892 892
893 893 Repositories with this on-disk format require Mercurial version 1.1.
894 894
895 895 Enabled by default.
896 896
897 897 ``use-persistent-nodemap``
898 898 Enable or disable the "persistent-nodemap" feature which improves
899 899 performance if the rust extensions are available.
900 900
901 901 The "persistence-nodemap" persist the "node -> rev" on disk removing the
902 902 need to dynamically build that mapping for each Mercurial invocation. This
903 903 significantly reduce the startup cost of various local and server-side
904 904 operation for larger repository.
905 905
906 906 The performance improving version of this feature is currently only
907 907 implemented in Rust, so people not using a version of Mercurial compiled
908 908 with the Rust part might actually suffer some slowdown. For this reason,
909 909 Such version will by default refuse to access such repositories. That
910 910 behavior can be controlled by configuration. Check
911 911 :hg:`help config.storage.revlog.persistent-nodemap.slowpath` for details.
912 912
913 913 Repository with this on-disk format require Mercurial version 5.4 or above.
914 914
915 915 Disabled by default.
916 916
917 917 ``usestore``
918 918 Enable or disable the "store" repository format which improves
919 919 compatibility with systems that fold case or otherwise mangle
920 920 filenames. Disabling this option will allow you to store longer filenames
921 921 in some situations at the expense of compatibility.
922 922
923 923 Repositories with this on-disk format require Mercurial version 0.9.4.
924 924
925 925 Enabled by default.
926 926
927 927 ``sparse-revlog``
928 928 Enable or disable the ``sparse-revlog`` delta strategy. This format improves
929 929 delta re-use inside revlog. For very branchy repositories, it results in a
930 930 smaller store. For repositories with many revisions, it also helps
931 931 performance (by using shortened delta chains.)
932 932
933 933 Repositories with this on-disk format require Mercurial version 4.7
934 934
935 935 Enabled by default.
936 936
937 937 ``revlog-compression``
938 938 Compression algorithm used by revlog. Supported values are `zlib` and
939 939 `zstd`. The `zlib` engine is the historical default of Mercurial. `zstd` is
940 940 a newer format that is usually a net win over `zlib`, operating faster at
941 941 better compression rates. Use `zstd` to reduce CPU usage. Multiple values
942 942 can be specified, the first available one will be used.
943 943
944 944 On some systems, the Mercurial installation may lack `zstd` support.
945 945
946 946 Default is `zlib`.
947 947
948 948 ``bookmarks-in-store``
949 949 Store bookmarks in .hg/store/. This means that bookmarks are shared when
950 950 using `hg share` regardless of the `-B` option.
951 951
952 952 Repositories with this on-disk format require Mercurial version 5.1.
953 953
954 954 Disabled by default.
955 955
956 956
957 957 ``graph``
958 958 ---------
959 959
960 960 Web graph view configuration. This section let you change graph
961 961 elements display properties by branches, for instance to make the
962 962 ``default`` branch stand out.
963 963
964 964 Each line has the following format::
965 965
966 966 <branch>.<argument> = <value>
967 967
968 968 where ``<branch>`` is the name of the branch being
969 969 customized. Example::
970 970
971 971 [graph]
972 972 # 2px width
973 973 default.width = 2
974 974 # red color
975 975 default.color = FF0000
976 976
977 977 Supported arguments:
978 978
979 979 ``width``
980 980 Set branch edges width in pixels.
981 981
982 982 ``color``
983 983 Set branch edges color in hexadecimal RGB notation.
984 984
985 985 ``hooks``
986 986 ---------
987 987
988 988 Commands or Python functions that get automatically executed by
989 989 various actions such as starting or finishing a commit. Multiple
990 990 hooks can be run for the same action by appending a suffix to the
991 991 action. Overriding a site-wide hook can be done by changing its
992 992 value or setting it to an empty string. Hooks can be prioritized
993 993 by adding a prefix of ``priority.`` to the hook name on a new line
994 994 and setting the priority. The default priority is 0.
995 995
996 996 Example ``.hg/hgrc``::
997 997
998 998 [hooks]
999 999 # update working directory after adding changesets
1000 1000 changegroup.update = hg update
1001 1001 # do not use the site-wide hook
1002 1002 incoming =
1003 1003 incoming.email = /my/email/hook
1004 1004 incoming.autobuild = /my/build/hook
1005 1005 # force autobuild hook to run before other incoming hooks
1006 1006 priority.incoming.autobuild = 1
1007 1007
1008 1008 Most hooks are run with environment variables set that give useful
1009 1009 additional information. For each hook below, the environment variables
1010 1010 it is passed are listed with names in the form ``$HG_foo``. The
1011 1011 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
1012 1012 They contain the type of hook which triggered the run and the full name
1013 1013 of the hook in the config, respectively. In the example above, this will
1014 1014 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
1015 1015
1016 1016 .. container:: windows
1017 1017
1018 1018 Some basic Unix syntax can be enabled for portability, including ``$VAR``
1019 1019 and ``${VAR}`` style variables. A ``~`` followed by ``\`` or ``/`` will
1020 1020 be expanded to ``%USERPROFILE%`` to simulate a subset of tilde expansion
1021 1021 on Unix. To use a literal ``$`` or ``~``, it must be escaped with a back
1022 1022 slash or inside of a strong quote. Strong quotes will be replaced by
1023 1023 double quotes after processing.
1024 1024
1025 1025 This feature is enabled by adding a prefix of ``tonative.`` to the hook
1026 1026 name on a new line, and setting it to ``True``. For example::
1027 1027
1028 1028 [hooks]
1029 1029 incoming.autobuild = /my/build/hook
1030 1030 # enable translation to cmd.exe syntax for autobuild hook
1031 1031 tonative.incoming.autobuild = True
1032 1032
1033 1033 ``changegroup``
1034 1034 Run after a changegroup has been added via push, pull or unbundle. The ID of
1035 1035 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
1036 1036 The URL from which changes came is in ``$HG_URL``.
1037 1037
1038 1038 ``commit``
1039 1039 Run after a changeset has been created in the local repository. The ID
1040 1040 of the newly created changeset is in ``$HG_NODE``. Parent changeset
1041 1041 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1042 1042
1043 1043 ``incoming``
1044 1044 Run after a changeset has been pulled, pushed, or unbundled into
1045 1045 the local repository. The ID of the newly arrived changeset is in
1046 1046 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
1047 1047
1048 1048 ``outgoing``
1049 1049 Run after sending changes from the local repository to another. The ID of
1050 1050 first changeset sent is in ``$HG_NODE``. The source of operation is in
1051 1051 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
1052 1052
1053 1053 ``post-<command>``
1054 1054 Run after successful invocations of the associated command. The
1055 1055 contents of the command line are passed as ``$HG_ARGS`` and the result
1056 1056 code in ``$HG_RESULT``. Parsed command line arguments are passed as
1057 1057 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
1058 1058 the python data internally passed to <command>. ``$HG_OPTS`` is a
1059 1059 dictionary of options (with unspecified options set to their defaults).
1060 1060 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
1061 1061
1062 1062 ``fail-<command>``
1063 1063 Run after a failed invocation of an associated command. The contents
1064 1064 of the command line are passed as ``$HG_ARGS``. Parsed command line
1065 1065 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
1066 1066 string representations of the python data internally passed to
1067 1067 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
1068 1068 options set to their defaults). ``$HG_PATS`` is a list of arguments.
1069 1069 Hook failure is ignored.
1070 1070
1071 1071 ``pre-<command>``
1072 1072 Run before executing the associated command. The contents of the
1073 1073 command line are passed as ``$HG_ARGS``. Parsed command line arguments
1074 1074 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
1075 1075 representations of the data internally passed to <command>. ``$HG_OPTS``
1076 1076 is a dictionary of options (with unspecified options set to their
1077 1077 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
1078 1078 failure, the command doesn't execute and Mercurial returns the failure
1079 1079 code.
1080 1080
1081 1081 ``prechangegroup``
1082 1082 Run before a changegroup is added via push, pull or unbundle. Exit
1083 1083 status 0 allows the changegroup to proceed. A non-zero status will
1084 1084 cause the push, pull or unbundle to fail. The URL from which changes
1085 1085 will come is in ``$HG_URL``.
1086 1086
1087 1087 ``precommit``
1088 1088 Run before starting a local commit. Exit status 0 allows the
1089 1089 commit to proceed. A non-zero status will cause the commit to fail.
1090 1090 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1091 1091
1092 1092 ``prelistkeys``
1093 1093 Run before listing pushkeys (like bookmarks) in the
1094 1094 repository. A non-zero status will cause failure. The key namespace is
1095 1095 in ``$HG_NAMESPACE``.
1096 1096
1097 1097 ``preoutgoing``
1098 1098 Run before collecting changes to send from the local repository to
1099 1099 another. A non-zero status will cause failure. This lets you prevent
1100 1100 pull over HTTP or SSH. It can also prevent propagating commits (via
1101 1101 local pull, push (outbound) or bundle commands), but not completely,
1102 1102 since you can just copy files instead. The source of operation is in
1103 1103 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
1104 1104 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
1105 1105 is happening on behalf of a repository on same system.
1106 1106
1107 1107 ``prepushkey``
1108 1108 Run before a pushkey (like a bookmark) is added to the
1109 1109 repository. A non-zero status will cause the key to be rejected. The
1110 1110 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
1111 1111 the old value (if any) is in ``$HG_OLD``, and the new value is in
1112 1112 ``$HG_NEW``.
1113 1113
1114 1114 ``pretag``
1115 1115 Run before creating a tag. Exit status 0 allows the tag to be
1116 1116 created. A non-zero status will cause the tag to fail. The ID of the
1117 1117 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
1118 1118 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
1119 1119
1120 1120 ``pretxnopen``
1121 1121 Run before any new repository transaction is open. The reason for the
1122 1122 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
1123 1123 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
1124 1124 transaction from being opened.
1125 1125
1126 1126 ``pretxnclose``
1127 1127 Run right before the transaction is actually finalized. Any repository change
1128 1128 will be visible to the hook program. This lets you validate the transaction
1129 1129 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1130 1130 status will cause the transaction to be rolled back. The reason for the
1131 1131 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
1132 1132 the transaction will be in ``HG_TXNID``. The rest of the available data will
1133 1133 vary according the transaction type. New changesets will add ``$HG_NODE``
1134 1134 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
1135 1135 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
1136 1136 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
1137 1137 respectively, etc.
1138 1138
1139 1139 ``pretxnclose-bookmark``
1140 1140 Run right before a bookmark change is actually finalized. Any repository
1141 1141 change will be visible to the hook program. This lets you validate the
1142 1142 transaction content or change it. Exit status 0 allows the commit to
1143 1143 proceed. A non-zero status will cause the transaction to be rolled back.
1144 1144 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
1145 1145 bookmark location will be available in ``$HG_NODE`` while the previous
1146 1146 location will be available in ``$HG_OLDNODE``. In case of a bookmark
1147 1147 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1148 1148 will be empty.
1149 1149 In addition, the reason for the transaction opening will be in
1150 1150 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1151 1151 ``HG_TXNID``.
1152 1152
1153 1153 ``pretxnclose-phase``
1154 1154 Run right before a phase change is actually finalized. Any repository change
1155 1155 will be visible to the hook program. This lets you validate the transaction
1156 1156 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1157 1157 status will cause the transaction to be rolled back. The hook is called
1158 1158 multiple times, once for each revision affected by a phase change.
1159 1159 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1160 1160 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1161 1161 will be empty. In addition, the reason for the transaction opening will be in
1162 1162 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1163 1163 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1164 1164 the ``$HG_OLDPHASE`` entry will be empty.
1165 1165
1166 1166 ``txnclose``
1167 1167 Run after any repository transaction has been committed. At this
1168 1168 point, the transaction can no longer be rolled back. The hook will run
1169 1169 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1170 1170 details about available variables.
1171 1171
1172 1172 ``txnclose-bookmark``
1173 1173 Run after any bookmark change has been committed. At this point, the
1174 1174 transaction can no longer be rolled back. The hook will run after the lock
1175 1175 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1176 1176 about available variables.
1177 1177
1178 1178 ``txnclose-phase``
1179 1179 Run after any phase change has been committed. At this point, the
1180 1180 transaction can no longer be rolled back. The hook will run after the lock
1181 1181 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1182 1182 available variables.
1183 1183
1184 1184 ``txnabort``
1185 1185 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1186 1186 for details about available variables.
1187 1187
1188 1188 ``pretxnchangegroup``
1189 1189 Run after a changegroup has been added via push, pull or unbundle, but before
1190 1190 the transaction has been committed. The changegroup is visible to the hook
1191 1191 program. This allows validation of incoming changes before accepting them.
1192 1192 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1193 1193 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1194 1194 status will cause the transaction to be rolled back, and the push, pull or
1195 1195 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1196 1196
1197 1197 ``pretxncommit``
1198 1198 Run after a changeset has been created, but before the transaction is
1199 1199 committed. The changeset is visible to the hook program. This allows
1200 1200 validation of the commit message and changes. Exit status 0 allows the
1201 1201 commit to proceed. A non-zero status will cause the transaction to
1202 1202 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1203 1203 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1204 1204
1205 1205 ``preupdate``
1206 1206 Run before updating the working directory. Exit status 0 allows
1207 1207 the update to proceed. A non-zero status will prevent the update.
1208 1208 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1209 1209 merge, the ID of second new parent is in ``$HG_PARENT2``.
1210 1210
1211 1211 ``listkeys``
1212 1212 Run after listing pushkeys (like bookmarks) in the repository. The
1213 1213 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1214 1214 dictionary containing the keys and values.
1215 1215
1216 1216 ``pushkey``
1217 1217 Run after a pushkey (like a bookmark) is added to the
1218 1218 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1219 1219 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1220 1220 value is in ``$HG_NEW``.
1221 1221
1222 1222 ``tag``
1223 1223 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1224 1224 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1225 1225 the repository if ``$HG_LOCAL=0``.
1226 1226
1227 1227 ``update``
1228 1228 Run after updating the working directory. The changeset ID of first
1229 1229 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1230 1230 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1231 1231 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1232 1232
1233 1233 .. note::
1234 1234
1235 1235 It is generally better to use standard hooks rather than the
1236 1236 generic pre- and post- command hooks, as they are guaranteed to be
1237 1237 called in the appropriate contexts for influencing transactions.
1238 1238 Also, hooks like "commit" will be called in all contexts that
1239 1239 generate a commit (e.g. tag) and not just the commit command.
1240 1240
1241 1241 .. note::
1242 1242
1243 1243 Environment variables with empty values may not be passed to
1244 1244 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1245 1245 will have an empty value under Unix-like platforms for non-merge
1246 1246 changesets, while it will not be available at all under Windows.
1247 1247
1248 1248 The syntax for Python hooks is as follows::
1249 1249
1250 1250 hookname = python:modulename.submodule.callable
1251 1251 hookname = python:/path/to/python/module.py:callable
1252 1252
1253 1253 Python hooks are run within the Mercurial process. Each hook is
1254 1254 called with at least three keyword arguments: a ui object (keyword
1255 1255 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1256 1256 keyword that tells what kind of hook is used. Arguments listed as
1257 1257 environment variables above are passed as keyword arguments, with no
1258 1258 ``HG_`` prefix, and names in lower case.
1259 1259
1260 1260 If a Python hook returns a "true" value or raises an exception, this
1261 1261 is treated as a failure.
1262 1262
1263 1263
1264 1264 ``hostfingerprints``
1265 1265 --------------------
1266 1266
1267 1267 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1268 1268
1269 1269 Fingerprints of the certificates of known HTTPS servers.
1270 1270
1271 1271 A HTTPS connection to a server with a fingerprint configured here will
1272 1272 only succeed if the servers certificate matches the fingerprint.
1273 1273 This is very similar to how ssh known hosts works.
1274 1274
1275 1275 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1276 1276 Multiple values can be specified (separated by spaces or commas). This can
1277 1277 be used to define both old and new fingerprints while a host transitions
1278 1278 to a new certificate.
1279 1279
1280 1280 The CA chain and web.cacerts is not used for servers with a fingerprint.
1281 1281
1282 1282 For example::
1283 1283
1284 1284 [hostfingerprints]
1285 1285 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1286 1286 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1287 1287
1288 1288 ``hostsecurity``
1289 1289 ----------------
1290 1290
1291 1291 Used to specify global and per-host security settings for connecting to
1292 1292 other machines.
1293 1293
1294 1294 The following options control default behavior for all hosts.
1295 1295
1296 1296 ``ciphers``
1297 1297 Defines the cryptographic ciphers to use for connections.
1298 1298
1299 1299 Value must be a valid OpenSSL Cipher List Format as documented at
1300 1300 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1301 1301
1302 1302 This setting is for advanced users only. Setting to incorrect values
1303 1303 can significantly lower connection security or decrease performance.
1304 1304 You have been warned.
1305 1305
1306 1306 This option requires Python 2.7.
1307 1307
1308 1308 ``minimumprotocol``
1309 1309 Defines the minimum channel encryption protocol to use.
1310 1310
1311 1311 By default, the highest version of TLS supported by both client and server
1312 1312 is used.
1313 1313
1314 1314 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1315 1315
1316 1316 When running on an old Python version, only ``tls1.0`` is allowed since
1317 1317 old versions of Python only support up to TLS 1.0.
1318 1318
1319 1319 When running a Python that supports modern TLS versions, the default is
1320 1320 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1321 1321 weakens security and should only be used as a feature of last resort if
1322 1322 a server does not support TLS 1.1+.
1323 1323
1324 1324 Options in the ``[hostsecurity]`` section can have the form
1325 1325 ``hostname``:``setting``. This allows multiple settings to be defined on a
1326 1326 per-host basis.
1327 1327
1328 1328 The following per-host settings can be defined.
1329 1329
1330 1330 ``ciphers``
1331 1331 This behaves like ``ciphers`` as described above except it only applies
1332 1332 to the host on which it is defined.
1333 1333
1334 1334 ``fingerprints``
1335 1335 A list of hashes of the DER encoded peer/remote certificate. Values have
1336 1336 the form ``algorithm``:``fingerprint``. e.g.
1337 1337 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1338 1338 In addition, colons (``:``) can appear in the fingerprint part.
1339 1339
1340 1340 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1341 1341 ``sha512``.
1342 1342
1343 1343 Use of ``sha256`` or ``sha512`` is preferred.
1344 1344
1345 1345 If a fingerprint is specified, the CA chain is not validated for this
1346 1346 host and Mercurial will require the remote certificate to match one
1347 1347 of the fingerprints specified. This means if the server updates its
1348 1348 certificate, Mercurial will abort until a new fingerprint is defined.
1349 1349 This can provide stronger security than traditional CA-based validation
1350 1350 at the expense of convenience.
1351 1351
1352 1352 This option takes precedence over ``verifycertsfile``.
1353 1353
1354 1354 ``minimumprotocol``
1355 1355 This behaves like ``minimumprotocol`` as described above except it
1356 1356 only applies to the host on which it is defined.
1357 1357
1358 1358 ``verifycertsfile``
1359 1359 Path to file a containing a list of PEM encoded certificates used to
1360 1360 verify the server certificate. Environment variables and ``~user``
1361 1361 constructs are expanded in the filename.
1362 1362
1363 1363 The server certificate or the certificate's certificate authority (CA)
1364 1364 must match a certificate from this file or certificate verification
1365 1365 will fail and connections to the server will be refused.
1366 1366
1367 1367 If defined, only certificates provided by this file will be used:
1368 1368 ``web.cacerts`` and any system/default certificates will not be
1369 1369 used.
1370 1370
1371 1371 This option has no effect if the per-host ``fingerprints`` option
1372 1372 is set.
1373 1373
1374 1374 The format of the file is as follows::
1375 1375
1376 1376 -----BEGIN CERTIFICATE-----
1377 1377 ... (certificate in base64 PEM encoding) ...
1378 1378 -----END CERTIFICATE-----
1379 1379 -----BEGIN CERTIFICATE-----
1380 1380 ... (certificate in base64 PEM encoding) ...
1381 1381 -----END CERTIFICATE-----
1382 1382
1383 1383 For example::
1384 1384
1385 1385 [hostsecurity]
1386 1386 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1387 1387 hg2.example.com:fingerprints = sha1:914f1aff87249c09b6859b88b1906d30756491ca, sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1388 1388 hg3.example.com:fingerprints = sha256:9a:b0:dc:e2:75:ad:8a:b7:84:58:e5:1f:07:32:f1:87:e6:bd:24:22:af:b7:ce:8e:9c:b4:10:cf:b9:f4:0e:d2
1389 1389 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1390 1390
1391 1391 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1392 1392 when connecting to ``hg.example.com``::
1393 1393
1394 1394 [hostsecurity]
1395 1395 minimumprotocol = tls1.2
1396 1396 hg.example.com:minimumprotocol = tls1.1
1397 1397
1398 1398 ``http_proxy``
1399 1399 --------------
1400 1400
1401 1401 Used to access web-based Mercurial repositories through a HTTP
1402 1402 proxy.
1403 1403
1404 1404 ``host``
1405 1405 Host name and (optional) port of the proxy server, for example
1406 1406 "myproxy:8000".
1407 1407
1408 1408 ``no``
1409 1409 Optional. Comma-separated list of host names that should bypass
1410 1410 the proxy.
1411 1411
1412 1412 ``passwd``
1413 1413 Optional. Password to authenticate with at the proxy server.
1414 1414
1415 1415 ``user``
1416 1416 Optional. User name to authenticate with at the proxy server.
1417 1417
1418 1418 ``always``
1419 1419 Optional. Always use the proxy, even for localhost and any entries
1420 1420 in ``http_proxy.no``. (default: False)
1421 1421
1422 1422 ``http``
1423 1423 ----------
1424 1424
1425 1425 Used to configure access to Mercurial repositories via HTTP.
1426 1426
1427 1427 ``timeout``
1428 1428 If set, blocking operations will timeout after that many seconds.
1429 1429 (default: None)
1430 1430
1431 1431 ``merge``
1432 1432 ---------
1433 1433
1434 1434 This section specifies behavior during merges and updates.
1435 1435
1436 1436 ``checkignored``
1437 1437 Controls behavior when an ignored file on disk has the same name as a tracked
1438 1438 file in the changeset being merged or updated to, and has different
1439 1439 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1440 1440 abort on such files. With ``warn``, warn on such files and back them up as
1441 1441 ``.orig``. With ``ignore``, don't print a warning and back them up as
1442 1442 ``.orig``. (default: ``abort``)
1443 1443
1444 1444 ``checkunknown``
1445 1445 Controls behavior when an unknown file that isn't ignored has the same name
1446 1446 as a tracked file in the changeset being merged or updated to, and has
1447 1447 different contents. Similar to ``merge.checkignored``, except for files that
1448 1448 are not ignored. (default: ``abort``)
1449 1449
1450 1450 ``on-failure``
1451 1451 When set to ``continue`` (the default), the merge process attempts to
1452 1452 merge all unresolved files using the merge chosen tool, regardless of
1453 1453 whether previous file merge attempts during the process succeeded or not.
1454 1454 Setting this to ``prompt`` will prompt after any merge failure continue
1455 1455 or halt the merge process. Setting this to ``halt`` will automatically
1456 1456 halt the merge process on any merge tool failure. The merge process
1457 1457 can be restarted by using the ``resolve`` command. When a merge is
1458 1458 halted, the repository is left in a normal ``unresolved`` merge state.
1459 1459 (default: ``continue``)
1460 1460
1461 1461 ``strict-capability-check``
1462 1462 Whether capabilities of internal merge tools are checked strictly
1463 1463 or not, while examining rules to decide merge tool to be used.
1464 1464 (default: False)
1465 1465
1466 1466 ``merge-patterns``
1467 1467 ------------------
1468 1468
1469 1469 This section specifies merge tools to associate with particular file
1470 1470 patterns. Tools matched here will take precedence over the default
1471 1471 merge tool. Patterns are globs by default, rooted at the repository
1472 1472 root.
1473 1473
1474 1474 Example::
1475 1475
1476 1476 [merge-patterns]
1477 1477 **.c = kdiff3
1478 1478 **.jpg = myimgmerge
1479 1479
1480 1480 ``merge-tools``
1481 1481 ---------------
1482 1482
1483 1483 This section configures external merge tools to use for file-level
1484 1484 merges. This section has likely been preconfigured at install time.
1485 1485 Use :hg:`config merge-tools` to check the existing configuration.
1486 1486 Also see :hg:`help merge-tools` for more details.
1487 1487
1488 1488 Example ``~/.hgrc``::
1489 1489
1490 1490 [merge-tools]
1491 1491 # Override stock tool location
1492 1492 kdiff3.executable = ~/bin/kdiff3
1493 1493 # Specify command line
1494 1494 kdiff3.args = $base $local $other -o $output
1495 1495 # Give higher priority
1496 1496 kdiff3.priority = 1
1497 1497
1498 1498 # Changing the priority of preconfigured tool
1499 1499 meld.priority = 0
1500 1500
1501 1501 # Disable a preconfigured tool
1502 1502 vimdiff.disabled = yes
1503 1503
1504 1504 # Define new tool
1505 1505 myHtmlTool.args = -m $local $other $base $output
1506 1506 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1507 1507 myHtmlTool.priority = 1
1508 1508
1509 1509 Supported arguments:
1510 1510
1511 1511 ``priority``
1512 1512 The priority in which to evaluate this tool.
1513 1513 (default: 0)
1514 1514
1515 1515 ``executable``
1516 1516 Either just the name of the executable or its pathname.
1517 1517
1518 1518 .. container:: windows
1519 1519
1520 1520 On Windows, the path can use environment variables with ${ProgramFiles}
1521 1521 syntax.
1522 1522
1523 1523 (default: the tool name)
1524 1524
1525 1525 ``args``
1526 1526 The arguments to pass to the tool executable. You can refer to the
1527 1527 files being merged as well as the output file through these
1528 1528 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1529 1529
1530 1530 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1531 1531 being performed. During an update or merge, ``$local`` represents the original
1532 1532 state of the file, while ``$other`` represents the commit you are updating to or
1533 1533 the commit you are merging with. During a rebase, ``$local`` represents the
1534 1534 destination of the rebase, and ``$other`` represents the commit being rebased.
1535 1535
1536 1536 Some operations define custom labels to assist with identifying the revisions,
1537 1537 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1538 1538 labels are not available, these will be ``local``, ``other``, and ``base``,
1539 1539 respectively.
1540 1540 (default: ``$local $base $other``)
1541 1541
1542 1542 ``premerge``
1543 1543 Attempt to run internal non-interactive 3-way merge tool before
1544 1544 launching external tool. Options are ``true``, ``false``, ``keep``,
1545 1545 ``keep-merge3``, or ``keep-mergediff`` (experimental). The ``keep`` option
1546 1546 will leave markers in the file if the premerge fails. The ``keep-merge3``
1547 1547 will do the same but include information about the base of the merge in the
1548 1548 marker (see internal :merge3 in :hg:`help merge-tools`). The
1549 1549 ``keep-mergediff`` option is similar but uses a different marker style
1550 1550 (see internal :merge3 in :hg:`help merge-tools`). (default: True)
1551 1551
1552 1552 ``binary``
1553 1553 This tool can merge binary files. (default: False, unless tool
1554 1554 was selected by file pattern match)
1555 1555
1556 1556 ``symlink``
1557 1557 This tool can merge symlinks. (default: False)
1558 1558
1559 1559 ``check``
1560 1560 A list of merge success-checking options:
1561 1561
1562 1562 ``changed``
1563 1563 Ask whether merge was successful when the merged file shows no changes.
1564 1564 ``conflicts``
1565 1565 Check whether there are conflicts even though the tool reported success.
1566 1566 ``prompt``
1567 1567 Always prompt for merge success, regardless of success reported by tool.
1568 1568
1569 1569 ``fixeol``
1570 1570 Attempt to fix up EOL changes caused by the merge tool.
1571 1571 (default: False)
1572 1572
1573 1573 ``gui``
1574 1574 This tool requires a graphical interface to run. (default: False)
1575 1575
1576 1576 ``mergemarkers``
1577 1577 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1578 1578 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1579 1579 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1580 1580 markers generated during premerge will be ``detailed`` if either this option or
1581 1581 the corresponding option in the ``[ui]`` section is ``detailed``.
1582 1582 (default: ``basic``)
1583 1583
1584 1584 ``mergemarkertemplate``
1585 1585 This setting can be used to override ``mergemarker`` from the
1586 1586 ``[command-templates]`` section on a per-tool basis; this applies to the
1587 1587 ``$label``-prefixed variables and to the conflict markers that are generated
1588 1588 if ``premerge`` is ``keep` or ``keep-merge3``. See the corresponding variable
1589 1589 in ``[ui]`` for more information.
1590 1590
1591 1591 .. container:: windows
1592 1592
1593 1593 ``regkey``
1594 1594 Windows registry key which describes install location of this
1595 1595 tool. Mercurial will search for this key first under
1596 1596 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1597 1597 (default: None)
1598 1598
1599 1599 ``regkeyalt``
1600 1600 An alternate Windows registry key to try if the first key is not
1601 1601 found. The alternate key uses the same ``regname`` and ``regappend``
1602 1602 semantics of the primary key. The most common use for this key
1603 1603 is to search for 32bit applications on 64bit operating systems.
1604 1604 (default: None)
1605 1605
1606 1606 ``regname``
1607 1607 Name of value to read from specified registry key.
1608 1608 (default: the unnamed (default) value)
1609 1609
1610 1610 ``regappend``
1611 1611 String to append to the value read from the registry, typically
1612 1612 the executable name of the tool.
1613 1613 (default: None)
1614 1614
1615 1615 ``pager``
1616 1616 ---------
1617 1617
1618 1618 Setting used to control when to paginate and with what external tool. See
1619 1619 :hg:`help pager` for details.
1620 1620
1621 1621 ``pager``
1622 1622 Define the external tool used as pager.
1623 1623
1624 1624 If no pager is set, Mercurial uses the environment variable $PAGER.
1625 1625 If neither pager.pager, nor $PAGER is set, a default pager will be
1626 1626 used, typically `less` on Unix and `more` on Windows. Example::
1627 1627
1628 1628 [pager]
1629 1629 pager = less -FRX
1630 1630
1631 1631 ``ignore``
1632 1632 List of commands to disable the pager for. Example::
1633 1633
1634 1634 [pager]
1635 1635 ignore = version, help, update
1636 1636
1637 1637 ``patch``
1638 1638 ---------
1639 1639
1640 1640 Settings used when applying patches, for instance through the 'import'
1641 1641 command or with Mercurial Queues extension.
1642 1642
1643 1643 ``eol``
1644 1644 When set to 'strict' patch content and patched files end of lines
1645 1645 are preserved. When set to ``lf`` or ``crlf``, both files end of
1646 1646 lines are ignored when patching and the result line endings are
1647 1647 normalized to either LF (Unix) or CRLF (Windows). When set to
1648 1648 ``auto``, end of lines are again ignored while patching but line
1649 1649 endings in patched files are normalized to their original setting
1650 1650 on a per-file basis. If target file does not exist or has no end
1651 1651 of line, patch line endings are preserved.
1652 1652 (default: strict)
1653 1653
1654 1654 ``fuzz``
1655 1655 The number of lines of 'fuzz' to allow when applying patches. This
1656 1656 controls how much context the patcher is allowed to ignore when
1657 1657 trying to apply a patch.
1658 1658 (default: 2)
1659 1659
1660 1660 ``paths``
1661 1661 ---------
1662 1662
1663 1663 Assigns symbolic names and behavior to repositories.
1664 1664
1665 1665 Options are symbolic names defining the URL or directory that is the
1666 1666 location of the repository. Example::
1667 1667
1668 1668 [paths]
1669 1669 my_server = https://example.com/my_repo
1670 1670 local_path = /home/me/repo
1671 1671
1672 1672 These symbolic names can be used from the command line. To pull
1673 1673 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1674 1674 :hg:`push local_path`.
1675 1675
1676 1676 Options containing colons (``:``) denote sub-options that can influence
1677 1677 behavior for that specific path. Example::
1678 1678
1679 1679 [paths]
1680 1680 my_server = https://example.com/my_path
1681 1681 my_server:pushurl = ssh://example.com/my_path
1682 1682
1683 1683 The following sub-options can be defined:
1684 1684
1685 1685 ``pushurl``
1686 1686 The URL to use for push operations. If not defined, the location
1687 1687 defined by the path's main entry is used.
1688 1688
1689 1689 ``pushrev``
1690 1690 A revset defining which revisions to push by default.
1691 1691
1692 1692 When :hg:`push` is executed without a ``-r`` argument, the revset
1693 1693 defined by this sub-option is evaluated to determine what to push.
1694 1694
1695 1695 For example, a value of ``.`` will push the working directory's
1696 1696 revision by default.
1697 1697
1698 1698 Revsets specifying bookmarks will not result in the bookmark being
1699 1699 pushed.
1700 1700
1701 1701 The following special named paths exist:
1702 1702
1703 1703 ``default``
1704 1704 The URL or directory to use when no source or remote is specified.
1705 1705
1706 1706 :hg:`clone` will automatically define this path to the location the
1707 1707 repository was cloned from.
1708 1708
1709 1709 ``default-push``
1710 1710 (deprecated) The URL or directory for the default :hg:`push` location.
1711 1711 ``default:pushurl`` should be used instead.
1712 1712
1713 1713 ``phases``
1714 1714 ----------
1715 1715
1716 1716 Specifies default handling of phases. See :hg:`help phases` for more
1717 1717 information about working with phases.
1718 1718
1719 1719 ``publish``
1720 1720 Controls draft phase behavior when working as a server. When true,
1721 1721 pushed changesets are set to public in both client and server and
1722 1722 pulled or cloned changesets are set to public in the client.
1723 1723 (default: True)
1724 1724
1725 1725 ``new-commit``
1726 1726 Phase of newly-created commits.
1727 1727 (default: draft)
1728 1728
1729 1729 ``checksubrepos``
1730 1730 Check the phase of the current revision of each subrepository. Allowed
1731 1731 values are "ignore", "follow" and "abort". For settings other than
1732 1732 "ignore", the phase of the current revision of each subrepository is
1733 1733 checked before committing the parent repository. If any of those phases is
1734 1734 greater than the phase of the parent repository (e.g. if a subrepo is in a
1735 1735 "secret" phase while the parent repo is in "draft" phase), the commit is
1736 1736 either aborted (if checksubrepos is set to "abort") or the higher phase is
1737 1737 used for the parent repository commit (if set to "follow").
1738 1738 (default: follow)
1739 1739
1740 1740
1741 1741 ``profiling``
1742 1742 -------------
1743 1743
1744 1744 Specifies profiling type, format, and file output. Two profilers are
1745 1745 supported: an instrumenting profiler (named ``ls``), and a sampling
1746 1746 profiler (named ``stat``).
1747 1747
1748 1748 In this section description, 'profiling data' stands for the raw data
1749 1749 collected during profiling, while 'profiling report' stands for a
1750 1750 statistical text report generated from the profiling data.
1751 1751
1752 1752 ``enabled``
1753 1753 Enable the profiler.
1754 1754 (default: false)
1755 1755
1756 1756 This is equivalent to passing ``--profile`` on the command line.
1757 1757
1758 1758 ``type``
1759 1759 The type of profiler to use.
1760 1760 (default: stat)
1761 1761
1762 1762 ``ls``
1763 1763 Use Python's built-in instrumenting profiler. This profiler
1764 1764 works on all platforms, but each line number it reports is the
1765 1765 first line of a function. This restriction makes it difficult to
1766 1766 identify the expensive parts of a non-trivial function.
1767 1767 ``stat``
1768 1768 Use a statistical profiler, statprof. This profiler is most
1769 1769 useful for profiling commands that run for longer than about 0.1
1770 1770 seconds.
1771 1771
1772 1772 ``format``
1773 1773 Profiling format. Specific to the ``ls`` instrumenting profiler.
1774 1774 (default: text)
1775 1775
1776 1776 ``text``
1777 1777 Generate a profiling report. When saving to a file, it should be
1778 1778 noted that only the report is saved, and the profiling data is
1779 1779 not kept.
1780 1780 ``kcachegrind``
1781 1781 Format profiling data for kcachegrind use: when saving to a
1782 1782 file, the generated file can directly be loaded into
1783 1783 kcachegrind.
1784 1784
1785 1785 ``statformat``
1786 1786 Profiling format for the ``stat`` profiler.
1787 1787 (default: hotpath)
1788 1788
1789 1789 ``hotpath``
1790 1790 Show a tree-based display containing the hot path of execution (where
1791 1791 most time was spent).
1792 1792 ``bymethod``
1793 1793 Show a table of methods ordered by how frequently they are active.
1794 1794 ``byline``
1795 1795 Show a table of lines in files ordered by how frequently they are active.
1796 1796 ``json``
1797 1797 Render profiling data as JSON.
1798 1798
1799 1799 ``frequency``
1800 1800 Sampling frequency. Specific to the ``stat`` sampling profiler.
1801 1801 (default: 1000)
1802 1802
1803 1803 ``output``
1804 1804 File path where profiling data or report should be saved. If the
1805 1805 file exists, it is replaced. (default: None, data is printed on
1806 1806 stderr)
1807 1807
1808 1808 ``sort``
1809 1809 Sort field. Specific to the ``ls`` instrumenting profiler.
1810 1810 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1811 1811 ``inlinetime``.
1812 1812 (default: inlinetime)
1813 1813
1814 1814 ``time-track``
1815 1815 Control if the stat profiler track ``cpu`` or ``real`` time.
1816 1816 (default: ``cpu`` on Windows, otherwise ``real``)
1817 1817
1818 1818 ``limit``
1819 1819 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1820 1820 (default: 30)
1821 1821
1822 1822 ``nested``
1823 1823 Show at most this number of lines of drill-down info after each main entry.
1824 1824 This can help explain the difference between Total and Inline.
1825 1825 Specific to the ``ls`` instrumenting profiler.
1826 1826 (default: 0)
1827 1827
1828 1828 ``showmin``
1829 1829 Minimum fraction of samples an entry must have for it to be displayed.
1830 1830 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1831 1831 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1832 1832
1833 1833 Only used by the ``stat`` profiler.
1834 1834
1835 1835 For the ``hotpath`` format, default is ``0.05``.
1836 1836 For the ``chrome`` format, default is ``0.005``.
1837 1837
1838 1838 The option is unused on other formats.
1839 1839
1840 1840 ``showmax``
1841 1841 Maximum fraction of samples an entry can have before it is ignored in
1842 1842 display. Values format is the same as ``showmin``.
1843 1843
1844 1844 Only used by the ``stat`` profiler.
1845 1845
1846 1846 For the ``chrome`` format, default is ``0.999``.
1847 1847
1848 1848 The option is unused on other formats.
1849 1849
1850 1850 ``showtime``
1851 1851 Show time taken as absolute durations, in addition to percentages.
1852 1852 Only used by the ``hotpath`` format.
1853 1853 (default: true)
1854 1854
1855 1855 ``progress``
1856 1856 ------------
1857 1857
1858 1858 Mercurial commands can draw progress bars that are as informative as
1859 1859 possible. Some progress bars only offer indeterminate information, while others
1860 1860 have a definite end point.
1861 1861
1862 1862 ``debug``
1863 1863 Whether to print debug info when updating the progress bar. (default: False)
1864 1864
1865 1865 ``delay``
1866 1866 Number of seconds (float) before showing the progress bar. (default: 3)
1867 1867
1868 1868 ``changedelay``
1869 1869 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1870 1870 that value will be used instead. (default: 1)
1871 1871
1872 1872 ``estimateinterval``
1873 1873 Maximum sampling interval in seconds for speed and estimated time
1874 1874 calculation. (default: 60)
1875 1875
1876 1876 ``refresh``
1877 1877 Time in seconds between refreshes of the progress bar. (default: 0.1)
1878 1878
1879 1879 ``format``
1880 1880 Format of the progress bar.
1881 1881
1882 1882 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1883 1883 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1884 1884 last 20 characters of the item, but this can be changed by adding either
1885 1885 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1886 1886 first num characters.
1887 1887
1888 1888 (default: topic bar number estimate)
1889 1889
1890 1890 ``width``
1891 1891 If set, the maximum width of the progress information (that is, min(width,
1892 1892 term width) will be used).
1893 1893
1894 1894 ``clear-complete``
1895 1895 Clear the progress bar after it's done. (default: True)
1896 1896
1897 1897 ``disable``
1898 1898 If true, don't show a progress bar.
1899 1899
1900 1900 ``assume-tty``
1901 1901 If true, ALWAYS show a progress bar, unless disable is given.
1902 1902
1903 1903 ``rebase``
1904 1904 ----------
1905 1905
1906 1906 ``evolution.allowdivergence``
1907 1907 Default to False, when True allow creating divergence when performing
1908 1908 rebase of obsolete changesets.
1909 1909
1910 1910 ``revsetalias``
1911 1911 ---------------
1912 1912
1913 1913 Alias definitions for revsets. See :hg:`help revsets` for details.
1914 1914
1915 1915 ``rewrite``
1916 1916 -----------
1917 1917
1918 1918 ``backup-bundle``
1919 1919 Whether to save stripped changesets to a bundle file. (default: True)
1920 1920
1921 1921 ``update-timestamp``
1922 1922 If true, updates the date and time of the changeset to current. It is only
1923 1923 applicable for `hg amend`, `hg commit --amend` and `hg uncommit` in the
1924 1924 current version.
1925 1925
1926 1926 ``empty-successor``
1927 1927
1928 1928 Control what happens with empty successors that are the result of rewrite
1929 1929 operations. If set to ``skip``, the successor is not created. If set to
1930 1930 ``keep``, the empty successor is created and kept.
1931 1931
1932 1932 Currently, only the rebase and absorb commands consider this configuration.
1933 1933 (EXPERIMENTAL)
1934 1934
1935 ``share``
1936 ---------
1937
1938 ``safe-mismatch.source-safe``
1939
1940 Controls what happens when the shared repository does not use the
1941 share-safe mechanism but its source repository does.
1942
1943 Possible values are `abort` (default), `allow`, `upgrade-abort` and
1944 `upgrade-abort`.
1945 `abort`: Disallows running any command and aborts
1946 `allow`: Respects the feature presence in the share source
1947 `upgrade-abort`: tries to upgrade the share to use share-safe;
1948 if it fails, aborts
1949 `upgrade-allow`: tries to upgrade the share; if it fails, continue by
1950 respecting the share source setting
1951
1952 ``safe-mismatch.source-not-safe``
1953
1954 Controls what happens when the shared repository uses the share-safe
1955 mechanism but its source does not.
1956
1957 Possible values are `abort` (default), `allow`, `downgrade-abort` and
1958 `downgrade-abort`.
1959 `abort`: Disallows running any command and aborts
1960 `allow`: Respects the feature presence in the share source
1961 `downgrade-abort`: tries to downgrade the share to not use share-safe;
1962 if it fails, aborts
1963 `downgrade-allow`: tries to downgrade the share to not use share-safe;
1964 if it fails, continue by respecting the shared
1965 source setting
1966
1967
1935 1968 ``storage``
1936 1969 -----------
1937 1970
1938 1971 Control the strategy Mercurial uses internally to store history. Options in this
1939 1972 category impact performance and repository size.
1940 1973
1941 1974 ``revlog.optimize-delta-parent-choice``
1942 1975 When storing a merge revision, both parents will be equally considered as
1943 1976 a possible delta base. This results in better delta selection and improved
1944 1977 revlog compression. This option is enabled by default.
1945 1978
1946 1979 Turning this option off can result in large increase of repository size for
1947 1980 repository with many merges.
1948 1981
1949 1982 ``revlog.persistent-nodemap.mmap``
1950 1983 Whether to use the Operating System "memory mapping" feature (when
1951 1984 possible) to access the persistent nodemap data. This improve performance
1952 1985 and reduce memory pressure.
1953 1986
1954 1987 Default to True.
1955 1988
1956 1989 For details on the "persistent-nodemap" feature, see:
1957 1990 :hg:`help config format.use-persistent-nodemap`.
1958 1991
1959 1992 ``revlog.persistent-nodemap.slow-path``
1960 1993 Control the behavior of Merucrial when using a repository with "persistent"
1961 1994 nodemap with an installation of Mercurial without a fast implementation for
1962 1995 the feature:
1963 1996
1964 1997 ``allow``: Silently use the slower implementation to access the repository.
1965 1998 ``warn``: Warn, but use the slower implementation to access the repository.
1966 1999 ``abort``: Prevent access to such repositories. (This is the default)
1967 2000
1968 2001 For details on the "persistent-nodemap" feature, see:
1969 2002 :hg:`help config format.use-persistent-nodemap`.
1970 2003
1971 2004 ``revlog.reuse-external-delta-parent``
1972 2005 Control the order in which delta parents are considered when adding new
1973 2006 revisions from an external source.
1974 2007 (typically: apply bundle from `hg pull` or `hg push`).
1975 2008
1976 2009 New revisions are usually provided as a delta against other revisions. By
1977 2010 default, Mercurial will try to reuse this delta first, therefore using the
1978 2011 same "delta parent" as the source. Directly using delta's from the source
1979 2012 reduces CPU usage and usually speeds up operation. However, in some case,
1980 2013 the source might have sub-optimal delta bases and forcing their reevaluation
1981 2014 is useful. For example, pushes from an old client could have sub-optimal
1982 2015 delta's parent that the server want to optimize. (lack of general delta, bad
1983 2016 parents, choice, lack of sparse-revlog, etc).
1984 2017
1985 2018 This option is enabled by default. Turning it off will ensure bad delta
1986 2019 parent choices from older client do not propagate to this repository, at
1987 2020 the cost of a small increase in CPU consumption.
1988 2021
1989 2022 Note: this option only control the order in which delta parents are
1990 2023 considered. Even when disabled, the existing delta from the source will be
1991 2024 reused if the same delta parent is selected.
1992 2025
1993 2026 ``revlog.reuse-external-delta``
1994 2027 Control the reuse of delta from external source.
1995 2028 (typically: apply bundle from `hg pull` or `hg push`).
1996 2029
1997 2030 New revisions are usually provided as a delta against another revision. By
1998 2031 default, Mercurial will not recompute the same delta again, trusting
1999 2032 externally provided deltas. There have been rare cases of small adjustment
2000 2033 to the diffing algorithm in the past. So in some rare case, recomputing
2001 2034 delta provided by ancient clients can provides better results. Disabling
2002 2035 this option means going through a full delta recomputation for all incoming
2003 2036 revisions. It means a large increase in CPU usage and will slow operations
2004 2037 down.
2005 2038
2006 2039 This option is enabled by default. When disabled, it also disables the
2007 2040 related ``storage.revlog.reuse-external-delta-parent`` option.
2008 2041
2009 2042 ``revlog.zlib.level``
2010 2043 Zlib compression level used when storing data into the repository. Accepted
2011 2044 Value range from 1 (lowest compression) to 9 (highest compression). Zlib
2012 2045 default value is 6.
2013 2046
2014 2047
2015 2048 ``revlog.zstd.level``
2016 2049 zstd compression level used when storing data into the repository. Accepted
2017 2050 Value range from 1 (lowest compression) to 22 (highest compression).
2018 2051 (default 3)
2019 2052
2020 2053 ``server``
2021 2054 ----------
2022 2055
2023 2056 Controls generic server settings.
2024 2057
2025 2058 ``bookmarks-pushkey-compat``
2026 2059 Trigger pushkey hook when being pushed bookmark updates. This config exist
2027 2060 for compatibility purpose (default to True)
2028 2061
2029 2062 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
2030 2063 movement we recommend you migrate them to ``txnclose-bookmark`` and
2031 2064 ``pretxnclose-bookmark``.
2032 2065
2033 2066 ``compressionengines``
2034 2067 List of compression engines and their relative priority to advertise
2035 2068 to clients.
2036 2069
2037 2070 The order of compression engines determines their priority, the first
2038 2071 having the highest priority. If a compression engine is not listed
2039 2072 here, it won't be advertised to clients.
2040 2073
2041 2074 If not set (the default), built-in defaults are used. Run
2042 2075 :hg:`debuginstall` to list available compression engines and their
2043 2076 default wire protocol priority.
2044 2077
2045 2078 Older Mercurial clients only support zlib compression and this setting
2046 2079 has no effect for legacy clients.
2047 2080
2048 2081 ``uncompressed``
2049 2082 Whether to allow clients to clone a repository using the
2050 2083 uncompressed streaming protocol. This transfers about 40% more
2051 2084 data than a regular clone, but uses less memory and CPU on both
2052 2085 server and client. Over a LAN (100 Mbps or better) or a very fast
2053 2086 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
2054 2087 regular clone. Over most WAN connections (anything slower than
2055 2088 about 6 Mbps), uncompressed streaming is slower, because of the
2056 2089 extra data transfer overhead. This mode will also temporarily hold
2057 2090 the write lock while determining what data to transfer.
2058 2091 (default: True)
2059 2092
2060 2093 ``uncompressedallowsecret``
2061 2094 Whether to allow stream clones when the repository contains secret
2062 2095 changesets. (default: False)
2063 2096
2064 2097 ``preferuncompressed``
2065 2098 When set, clients will try to use the uncompressed streaming
2066 2099 protocol. (default: False)
2067 2100
2068 2101 ``disablefullbundle``
2069 2102 When set, servers will refuse attempts to do pull-based clones.
2070 2103 If this option is set, ``preferuncompressed`` and/or clone bundles
2071 2104 are highly recommended. Partial clones will still be allowed.
2072 2105 (default: False)
2073 2106
2074 2107 ``streamunbundle``
2075 2108 When set, servers will apply data sent from the client directly,
2076 2109 otherwise it will be written to a temporary file first. This option
2077 2110 effectively prevents concurrent pushes.
2078 2111
2079 2112 ``pullbundle``
2080 2113 When set, the server will check pullbundle.manifest for bundles
2081 2114 covering the requested heads and common nodes. The first matching
2082 2115 entry will be streamed to the client.
2083 2116
2084 2117 For HTTP transport, the stream will still use zlib compression
2085 2118 for older clients.
2086 2119
2087 2120 ``concurrent-push-mode``
2088 2121 Level of allowed race condition between two pushing clients.
2089 2122
2090 2123 - 'strict': push is abort if another client touched the repository
2091 2124 while the push was preparing.
2092 2125 - 'check-related': push is only aborted if it affects head that got also
2093 2126 affected while the push was preparing. (default since 5.4)
2094 2127
2095 2128 'check-related' only takes effect for compatible clients (version
2096 2129 4.3 and later). Older clients will use 'strict'.
2097 2130
2098 2131 ``validate``
2099 2132 Whether to validate the completeness of pushed changesets by
2100 2133 checking that all new file revisions specified in manifests are
2101 2134 present. (default: False)
2102 2135
2103 2136 ``maxhttpheaderlen``
2104 2137 Instruct HTTP clients not to send request headers longer than this
2105 2138 many bytes. (default: 1024)
2106 2139
2107 2140 ``bundle1``
2108 2141 Whether to allow clients to push and pull using the legacy bundle1
2109 2142 exchange format. (default: True)
2110 2143
2111 2144 ``bundle1gd``
2112 2145 Like ``bundle1`` but only used if the repository is using the
2113 2146 *generaldelta* storage format. (default: True)
2114 2147
2115 2148 ``bundle1.push``
2116 2149 Whether to allow clients to push using the legacy bundle1 exchange
2117 2150 format. (default: True)
2118 2151
2119 2152 ``bundle1gd.push``
2120 2153 Like ``bundle1.push`` but only used if the repository is using the
2121 2154 *generaldelta* storage format. (default: True)
2122 2155
2123 2156 ``bundle1.pull``
2124 2157 Whether to allow clients to pull using the legacy bundle1 exchange
2125 2158 format. (default: True)
2126 2159
2127 2160 ``bundle1gd.pull``
2128 2161 Like ``bundle1.pull`` but only used if the repository is using the
2129 2162 *generaldelta* storage format. (default: True)
2130 2163
2131 2164 Large repositories using the *generaldelta* storage format should
2132 2165 consider setting this option because converting *generaldelta*
2133 2166 repositories to the exchange format required by the bundle1 data
2134 2167 format can consume a lot of CPU.
2135 2168
2136 2169 ``bundle2.stream``
2137 2170 Whether to allow clients to pull using the bundle2 streaming protocol.
2138 2171 (default: True)
2139 2172
2140 2173 ``zliblevel``
2141 2174 Integer between ``-1`` and ``9`` that controls the zlib compression level
2142 2175 for wire protocol commands that send zlib compressed output (notably the
2143 2176 commands that send repository history data).
2144 2177
2145 2178 The default (``-1``) uses the default zlib compression level, which is
2146 2179 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
2147 2180 maximum compression.
2148 2181
2149 2182 Setting this option allows server operators to make trade-offs between
2150 2183 bandwidth and CPU used. Lowering the compression lowers CPU utilization
2151 2184 but sends more bytes to clients.
2152 2185
2153 2186 This option only impacts the HTTP server.
2154 2187
2155 2188 ``zstdlevel``
2156 2189 Integer between ``1`` and ``22`` that controls the zstd compression level
2157 2190 for wire protocol commands. ``1`` is the minimal amount of compression and
2158 2191 ``22`` is the highest amount of compression.
2159 2192
2160 2193 The default (``3``) should be significantly faster than zlib while likely
2161 2194 delivering better compression ratios.
2162 2195
2163 2196 This option only impacts the HTTP server.
2164 2197
2165 2198 See also ``server.zliblevel``.
2166 2199
2167 2200 ``view``
2168 2201 Repository filter used when exchanging revisions with the peer.
2169 2202
2170 2203 The default view (``served``) excludes secret and hidden changesets.
2171 2204 Another useful value is ``immutable`` (no draft, secret or hidden
2172 2205 changesets). (EXPERIMENTAL)
2173 2206
2174 2207 ``smtp``
2175 2208 --------
2176 2209
2177 2210 Configuration for extensions that need to send email messages.
2178 2211
2179 2212 ``host``
2180 2213 Host name of mail server, e.g. "mail.example.com".
2181 2214
2182 2215 ``port``
2183 2216 Optional. Port to connect to on mail server. (default: 465 if
2184 2217 ``tls`` is smtps; 25 otherwise)
2185 2218
2186 2219 ``tls``
2187 2220 Optional. Method to enable TLS when connecting to mail server: starttls,
2188 2221 smtps or none. (default: none)
2189 2222
2190 2223 ``username``
2191 2224 Optional. User name for authenticating with the SMTP server.
2192 2225 (default: None)
2193 2226
2194 2227 ``password``
2195 2228 Optional. Password for authenticating with the SMTP server. If not
2196 2229 specified, interactive sessions will prompt the user for a
2197 2230 password; non-interactive sessions will fail. (default: None)
2198 2231
2199 2232 ``local_hostname``
2200 2233 Optional. The hostname that the sender can use to identify
2201 2234 itself to the MTA.
2202 2235
2203 2236
2204 2237 ``subpaths``
2205 2238 ------------
2206 2239
2207 2240 Subrepository source URLs can go stale if a remote server changes name
2208 2241 or becomes temporarily unavailable. This section lets you define
2209 2242 rewrite rules of the form::
2210 2243
2211 2244 <pattern> = <replacement>
2212 2245
2213 2246 where ``pattern`` is a regular expression matching a subrepository
2214 2247 source URL and ``replacement`` is the replacement string used to
2215 2248 rewrite it. Groups can be matched in ``pattern`` and referenced in
2216 2249 ``replacements``. For instance::
2217 2250
2218 2251 http://server/(.*)-hg/ = http://hg.server/\1/
2219 2252
2220 2253 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
2221 2254
2222 2255 Relative subrepository paths are first made absolute, and the
2223 2256 rewrite rules are then applied on the full (absolute) path. If ``pattern``
2224 2257 doesn't match the full path, an attempt is made to apply it on the
2225 2258 relative path alone. The rules are applied in definition order.
2226 2259
2227 2260 ``subrepos``
2228 2261 ------------
2229 2262
2230 2263 This section contains options that control the behavior of the
2231 2264 subrepositories feature. See also :hg:`help subrepos`.
2232 2265
2233 2266 Security note: auditing in Mercurial is known to be insufficient to
2234 2267 prevent clone-time code execution with carefully constructed Git
2235 2268 subrepos. It is unknown if a similar detect is present in Subversion
2236 2269 subrepos. Both Git and Subversion subrepos are disabled by default
2237 2270 out of security concerns. These subrepo types can be enabled using
2238 2271 the respective options below.
2239 2272
2240 2273 ``allowed``
2241 2274 Whether subrepositories are allowed in the working directory.
2242 2275
2243 2276 When false, commands involving subrepositories (like :hg:`update`)
2244 2277 will fail for all subrepository types.
2245 2278 (default: true)
2246 2279
2247 2280 ``hg:allowed``
2248 2281 Whether Mercurial subrepositories are allowed in the working
2249 2282 directory. This option only has an effect if ``subrepos.allowed``
2250 2283 is true.
2251 2284 (default: true)
2252 2285
2253 2286 ``git:allowed``
2254 2287 Whether Git subrepositories are allowed in the working directory.
2255 2288 This option only has an effect if ``subrepos.allowed`` is true.
2256 2289
2257 2290 See the security note above before enabling Git subrepos.
2258 2291 (default: false)
2259 2292
2260 2293 ``svn:allowed``
2261 2294 Whether Subversion subrepositories are allowed in the working
2262 2295 directory. This option only has an effect if ``subrepos.allowed``
2263 2296 is true.
2264 2297
2265 2298 See the security note above before enabling Subversion subrepos.
2266 2299 (default: false)
2267 2300
2268 2301 ``templatealias``
2269 2302 -----------------
2270 2303
2271 2304 Alias definitions for templates. See :hg:`help templates` for details.
2272 2305
2273 2306 ``templates``
2274 2307 -------------
2275 2308
2276 2309 Use the ``[templates]`` section to define template strings.
2277 2310 See :hg:`help templates` for details.
2278 2311
2279 2312 ``trusted``
2280 2313 -----------
2281 2314
2282 2315 Mercurial will not use the settings in the
2283 2316 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
2284 2317 user or to a trusted group, as various hgrc features allow arbitrary
2285 2318 commands to be run. This issue is often encountered when configuring
2286 2319 hooks or extensions for shared repositories or servers. However,
2287 2320 the web interface will use some safe settings from the ``[web]``
2288 2321 section.
2289 2322
2290 2323 This section specifies what users and groups are trusted. The
2291 2324 current user is always trusted. To trust everybody, list a user or a
2292 2325 group with name ``*``. These settings must be placed in an
2293 2326 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
2294 2327 user or service running Mercurial.
2295 2328
2296 2329 ``users``
2297 2330 Comma-separated list of trusted users.
2298 2331
2299 2332 ``groups``
2300 2333 Comma-separated list of trusted groups.
2301 2334
2302 2335
2303 2336 ``ui``
2304 2337 ------
2305 2338
2306 2339 User interface controls.
2307 2340
2308 2341 ``archivemeta``
2309 2342 Whether to include the .hg_archival.txt file containing meta data
2310 2343 (hashes for the repository base and for tip) in archives created
2311 2344 by the :hg:`archive` command or downloaded via hgweb.
2312 2345 (default: True)
2313 2346
2314 2347 ``askusername``
2315 2348 Whether to prompt for a username when committing. If True, and
2316 2349 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2317 2350 be prompted to enter a username. If no username is entered, the
2318 2351 default ``USER@HOST`` is used instead.
2319 2352 (default: False)
2320 2353
2321 2354 ``clonebundles``
2322 2355 Whether the "clone bundles" feature is enabled.
2323 2356
2324 2357 When enabled, :hg:`clone` may download and apply a server-advertised
2325 2358 bundle file from a URL instead of using the normal exchange mechanism.
2326 2359
2327 2360 This can likely result in faster and more reliable clones.
2328 2361
2329 2362 (default: True)
2330 2363
2331 2364 ``clonebundlefallback``
2332 2365 Whether failure to apply an advertised "clone bundle" from a server
2333 2366 should result in fallback to a regular clone.
2334 2367
2335 2368 This is disabled by default because servers advertising "clone
2336 2369 bundles" often do so to reduce server load. If advertised bundles
2337 2370 start mass failing and clients automatically fall back to a regular
2338 2371 clone, this would add significant and unexpected load to the server
2339 2372 since the server is expecting clone operations to be offloaded to
2340 2373 pre-generated bundles. Failing fast (the default behavior) ensures
2341 2374 clients don't overwhelm the server when "clone bundle" application
2342 2375 fails.
2343 2376
2344 2377 (default: False)
2345 2378
2346 2379 ``clonebundleprefers``
2347 2380 Defines preferences for which "clone bundles" to use.
2348 2381
2349 2382 Servers advertising "clone bundles" may advertise multiple available
2350 2383 bundles. Each bundle may have different attributes, such as the bundle
2351 2384 type and compression format. This option is used to prefer a particular
2352 2385 bundle over another.
2353 2386
2354 2387 The following keys are defined by Mercurial:
2355 2388
2356 2389 BUNDLESPEC
2357 2390 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2358 2391 e.g. ``gzip-v2`` or ``bzip2-v1``.
2359 2392
2360 2393 COMPRESSION
2361 2394 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2362 2395
2363 2396 Server operators may define custom keys.
2364 2397
2365 2398 Example values: ``COMPRESSION=bzip2``,
2366 2399 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2367 2400
2368 2401 By default, the first bundle advertised by the server is used.
2369 2402
2370 2403 ``color``
2371 2404 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2372 2405 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2373 2406 seems possible. See :hg:`help color` for details.
2374 2407
2375 2408 ``commitsubrepos``
2376 2409 Whether to commit modified subrepositories when committing the
2377 2410 parent repository. If False and one subrepository has uncommitted
2378 2411 changes, abort the commit.
2379 2412 (default: False)
2380 2413
2381 2414 ``debug``
2382 2415 Print debugging information. (default: False)
2383 2416
2384 2417 ``editor``
2385 2418 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2386 2419
2387 2420 ``fallbackencoding``
2388 2421 Encoding to try if it's not possible to decode the changelog using
2389 2422 UTF-8. (default: ISO-8859-1)
2390 2423
2391 2424 ``graphnodetemplate``
2392 2425 (DEPRECATED) Use ``command-templates.graphnode`` instead.
2393 2426
2394 2427 ``ignore``
2395 2428 A file to read per-user ignore patterns from. This file should be
2396 2429 in the same format as a repository-wide .hgignore file. Filenames
2397 2430 are relative to the repository root. This option supports hook syntax,
2398 2431 so if you want to specify multiple ignore files, you can do so by
2399 2432 setting something like ``ignore.other = ~/.hgignore2``. For details
2400 2433 of the ignore file format, see the ``hgignore(5)`` man page.
2401 2434
2402 2435 ``interactive``
2403 2436 Allow to prompt the user. (default: True)
2404 2437
2405 2438 ``interface``
2406 2439 Select the default interface for interactive features (default: text).
2407 2440 Possible values are 'text' and 'curses'.
2408 2441
2409 2442 ``interface.chunkselector``
2410 2443 Select the interface for change recording (e.g. :hg:`commit -i`).
2411 2444 Possible values are 'text' and 'curses'.
2412 2445 This config overrides the interface specified by ui.interface.
2413 2446
2414 2447 ``large-file-limit``
2415 2448 Largest file size that gives no memory use warning.
2416 2449 Possible values are integers or 0 to disable the check.
2417 2450 (default: 10000000)
2418 2451
2419 2452 ``logtemplate``
2420 2453 (DEPRECATED) Use ``command-templates.log`` instead.
2421 2454
2422 2455 ``merge``
2423 2456 The conflict resolution program to use during a manual merge.
2424 2457 For more information on merge tools see :hg:`help merge-tools`.
2425 2458 For configuring merge tools see the ``[merge-tools]`` section.
2426 2459
2427 2460 ``mergemarkers``
2428 2461 Sets the merge conflict marker label styling. The ``detailed`` style
2429 2462 uses the ``command-templates.mergemarker`` setting to style the labels.
2430 2463 The ``basic`` style just uses 'local' and 'other' as the marker label.
2431 2464 One of ``basic`` or ``detailed``.
2432 2465 (default: ``basic``)
2433 2466
2434 2467 ``mergemarkertemplate``
2435 2468 (DEPRECATED) Use ``command-templates.mergemarker`` instead.
2436 2469
2437 2470 ``message-output``
2438 2471 Where to write status and error messages. (default: ``stdio``)
2439 2472
2440 2473 ``channel``
2441 2474 Use separate channel for structured output. (Command-server only)
2442 2475 ``stderr``
2443 2476 Everything to stderr.
2444 2477 ``stdio``
2445 2478 Status to stdout, and error to stderr.
2446 2479
2447 2480 ``origbackuppath``
2448 2481 The path to a directory used to store generated .orig files. If the path is
2449 2482 not a directory, one will be created. If set, files stored in this
2450 2483 directory have the same name as the original file and do not have a .orig
2451 2484 suffix.
2452 2485
2453 2486 ``paginate``
2454 2487 Control the pagination of command output (default: True). See :hg:`help pager`
2455 2488 for details.
2456 2489
2457 2490 ``patch``
2458 2491 An optional external tool that ``hg import`` and some extensions
2459 2492 will use for applying patches. By default Mercurial uses an
2460 2493 internal patch utility. The external tool must work as the common
2461 2494 Unix ``patch`` program. In particular, it must accept a ``-p``
2462 2495 argument to strip patch headers, a ``-d`` argument to specify the
2463 2496 current directory, a file name to patch, and a patch file to take
2464 2497 from stdin.
2465 2498
2466 2499 It is possible to specify a patch tool together with extra
2467 2500 arguments. For example, setting this option to ``patch --merge``
2468 2501 will use the ``patch`` program with its 2-way merge option.
2469 2502
2470 2503 ``portablefilenames``
2471 2504 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2472 2505 (default: ``warn``)
2473 2506
2474 2507 ``warn``
2475 2508 Print a warning message on POSIX platforms, if a file with a non-portable
2476 2509 filename is added (e.g. a file with a name that can't be created on
2477 2510 Windows because it contains reserved parts like ``AUX``, reserved
2478 2511 characters like ``:``, or would cause a case collision with an existing
2479 2512 file).
2480 2513
2481 2514 ``ignore``
2482 2515 Don't print a warning.
2483 2516
2484 2517 ``abort``
2485 2518 The command is aborted.
2486 2519
2487 2520 ``true``
2488 2521 Alias for ``warn``.
2489 2522
2490 2523 ``false``
2491 2524 Alias for ``ignore``.
2492 2525
2493 2526 .. container:: windows
2494 2527
2495 2528 On Windows, this configuration option is ignored and the command aborted.
2496 2529
2497 2530 ``pre-merge-tool-output-template``
2498 2531 (DEPRECATED) Use ``command-template.pre-merge-tool-output`` instead.
2499 2532
2500 2533 ``quiet``
2501 2534 Reduce the amount of output printed.
2502 2535 (default: False)
2503 2536
2504 2537 ``relative-paths``
2505 2538 Prefer relative paths in the UI.
2506 2539
2507 2540 ``remotecmd``
2508 2541 Remote command to use for clone/push/pull operations.
2509 2542 (default: ``hg``)
2510 2543
2511 2544 ``report_untrusted``
2512 2545 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2513 2546 trusted user or group.
2514 2547 (default: True)
2515 2548
2516 2549 ``slash``
2517 2550 (Deprecated. Use ``slashpath`` template filter instead.)
2518 2551
2519 2552 Display paths using a slash (``/``) as the path separator. This
2520 2553 only makes a difference on systems where the default path
2521 2554 separator is not the slash character (e.g. Windows uses the
2522 2555 backslash character (``\``)).
2523 2556 (default: False)
2524 2557
2525 2558 ``statuscopies``
2526 2559 Display copies in the status command.
2527 2560
2528 2561 ``ssh``
2529 2562 Command to use for SSH connections. (default: ``ssh``)
2530 2563
2531 2564 ``ssherrorhint``
2532 2565 A hint shown to the user in the case of SSH error (e.g.
2533 2566 ``Please see http://company/internalwiki/ssh.html``)
2534 2567
2535 2568 ``strict``
2536 2569 Require exact command names, instead of allowing unambiguous
2537 2570 abbreviations. (default: False)
2538 2571
2539 2572 ``style``
2540 2573 Name of style to use for command output.
2541 2574
2542 2575 ``supportcontact``
2543 2576 A URL where users should report a Mercurial traceback. Use this if you are a
2544 2577 large organisation with its own Mercurial deployment process and crash
2545 2578 reports should be addressed to your internal support.
2546 2579
2547 2580 ``textwidth``
2548 2581 Maximum width of help text. A longer line generated by ``hg help`` or
2549 2582 ``hg subcommand --help`` will be broken after white space to get this
2550 2583 width or the terminal width, whichever comes first.
2551 2584 A non-positive value will disable this and the terminal width will be
2552 2585 used. (default: 78)
2553 2586
2554 2587 ``timeout``
2555 2588 The timeout used when a lock is held (in seconds), a negative value
2556 2589 means no timeout. (default: 600)
2557 2590
2558 2591 ``timeout.warn``
2559 2592 Time (in seconds) before a warning is printed about held lock. A negative
2560 2593 value means no warning. (default: 0)
2561 2594
2562 2595 ``traceback``
2563 2596 Mercurial always prints a traceback when an unknown exception
2564 2597 occurs. Setting this to True will make Mercurial print a traceback
2565 2598 on all exceptions, even those recognized by Mercurial (such as
2566 2599 IOError or MemoryError). (default: False)
2567 2600
2568 2601 ``tweakdefaults``
2569 2602
2570 2603 By default Mercurial's behavior changes very little from release
2571 2604 to release, but over time the recommended config settings
2572 2605 shift. Enable this config to opt in to get automatic tweaks to
2573 2606 Mercurial's behavior over time. This config setting will have no
2574 2607 effect if ``HGPLAIN`` is set or ``HGPLAINEXCEPT`` is set and does
2575 2608 not include ``tweakdefaults``. (default: False)
2576 2609
2577 2610 It currently means::
2578 2611
2579 2612 .. tweakdefaultsmarker
2580 2613
2581 2614 ``username``
2582 2615 The committer of a changeset created when running "commit".
2583 2616 Typically a person's name and email address, e.g. ``Fred Widget
2584 2617 <fred@example.com>``. Environment variables in the
2585 2618 username are expanded.
2586 2619
2587 2620 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2588 2621 hgrc is empty, e.g. if the system admin set ``username =`` in the
2589 2622 system hgrc, it has to be specified manually or in a different
2590 2623 hgrc file)
2591 2624
2592 2625 ``verbose``
2593 2626 Increase the amount of output printed. (default: False)
2594 2627
2595 2628
2596 2629 ``command-templates``
2597 2630 ---------------------
2598 2631
2599 2632 Templates used for customizing the output of commands.
2600 2633
2601 2634 ``graphnode``
2602 2635 The template used to print changeset nodes in an ASCII revision graph.
2603 2636 (default: ``{graphnode}``)
2604 2637
2605 2638 ``log``
2606 2639 Template string for commands that print changesets.
2607 2640
2608 2641 ``mergemarker``
2609 2642 The template used to print the commit description next to each conflict
2610 2643 marker during merge conflicts. See :hg:`help templates` for the template
2611 2644 format.
2612 2645
2613 2646 Defaults to showing the hash, tags, branches, bookmarks, author, and
2614 2647 the first line of the commit description.
2615 2648
2616 2649 If you use non-ASCII characters in names for tags, branches, bookmarks,
2617 2650 authors, and/or commit descriptions, you must pay attention to encodings of
2618 2651 managed files. At template expansion, non-ASCII characters use the encoding
2619 2652 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2620 2653 environment variables that govern your locale. If the encoding of the merge
2621 2654 markers is different from the encoding of the merged files,
2622 2655 serious problems may occur.
2623 2656
2624 2657 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2625 2658
2626 2659 ``oneline-summary``
2627 2660 A template used by `hg rebase` and other commands for showing a one-line
2628 2661 summary of a commit. If the template configured here is longer than one
2629 2662 line, then only the first line is used.
2630 2663
2631 2664 The template can be overridden per command by defining a template in
2632 2665 `oneline-summary.<command>`, where `<command>` can be e.g. "rebase".
2633 2666
2634 2667 ``pre-merge-tool-output``
2635 2668 A template that is printed before executing an external merge tool. This can
2636 2669 be used to print out additional context that might be useful to have during
2637 2670 the conflict resolution, such as the description of the various commits
2638 2671 involved or bookmarks/tags.
2639 2672
2640 2673 Additional information is available in the ``local`, ``base``, and ``other``
2641 2674 dicts. For example: ``{local.label}``, ``{base.name}``, or
2642 2675 ``{other.islink}``.
2643 2676
2644 2677
2645 2678 ``web``
2646 2679 -------
2647 2680
2648 2681 Web interface configuration. The settings in this section apply to
2649 2682 both the builtin webserver (started by :hg:`serve`) and the script you
2650 2683 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2651 2684 and WSGI).
2652 2685
2653 2686 The Mercurial webserver does no authentication (it does not prompt for
2654 2687 usernames and passwords to validate *who* users are), but it does do
2655 2688 authorization (it grants or denies access for *authenticated users*
2656 2689 based on settings in this section). You must either configure your
2657 2690 webserver to do authentication for you, or disable the authorization
2658 2691 checks.
2659 2692
2660 2693 For a quick setup in a trusted environment, e.g., a private LAN, where
2661 2694 you want it to accept pushes from anybody, you can use the following
2662 2695 command line::
2663 2696
2664 2697 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2665 2698
2666 2699 Note that this will allow anybody to push anything to the server and
2667 2700 that this should not be used for public servers.
2668 2701
2669 2702 The full set of options is:
2670 2703
2671 2704 ``accesslog``
2672 2705 Where to output the access log. (default: stdout)
2673 2706
2674 2707 ``address``
2675 2708 Interface address to bind to. (default: all)
2676 2709
2677 2710 ``allow-archive``
2678 2711 List of archive format (bz2, gz, zip) allowed for downloading.
2679 2712 (default: empty)
2680 2713
2681 2714 ``allowbz2``
2682 2715 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2683 2716 revisions.
2684 2717 (default: False)
2685 2718
2686 2719 ``allowgz``
2687 2720 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2688 2721 revisions.
2689 2722 (default: False)
2690 2723
2691 2724 ``allow-pull``
2692 2725 Whether to allow pulling from the repository. (default: True)
2693 2726
2694 2727 ``allow-push``
2695 2728 Whether to allow pushing to the repository. If empty or not set,
2696 2729 pushing is not allowed. If the special value ``*``, any remote
2697 2730 user can push, including unauthenticated users. Otherwise, the
2698 2731 remote user must have been authenticated, and the authenticated
2699 2732 user name must be present in this list. The contents of the
2700 2733 allow-push list are examined after the deny_push list.
2701 2734
2702 2735 ``allow_read``
2703 2736 If the user has not already been denied repository access due to
2704 2737 the contents of deny_read, this list determines whether to grant
2705 2738 repository access to the user. If this list is not empty, and the
2706 2739 user is unauthenticated or not present in the list, then access is
2707 2740 denied for the user. If the list is empty or not set, then access
2708 2741 is permitted to all users by default. Setting allow_read to the
2709 2742 special value ``*`` is equivalent to it not being set (i.e. access
2710 2743 is permitted to all users). The contents of the allow_read list are
2711 2744 examined after the deny_read list.
2712 2745
2713 2746 ``allowzip``
2714 2747 (DEPRECATED) Whether to allow .zip downloading of repository
2715 2748 revisions. This feature creates temporary files.
2716 2749 (default: False)
2717 2750
2718 2751 ``archivesubrepos``
2719 2752 Whether to recurse into subrepositories when archiving.
2720 2753 (default: False)
2721 2754
2722 2755 ``baseurl``
2723 2756 Base URL to use when publishing URLs in other locations, so
2724 2757 third-party tools like email notification hooks can construct
2725 2758 URLs. Example: ``http://hgserver/repos/``.
2726 2759
2727 2760 ``cacerts``
2728 2761 Path to file containing a list of PEM encoded certificate
2729 2762 authority certificates. Environment variables and ``~user``
2730 2763 constructs are expanded in the filename. If specified on the
2731 2764 client, then it will verify the identity of remote HTTPS servers
2732 2765 with these certificates.
2733 2766
2734 2767 To disable SSL verification temporarily, specify ``--insecure`` from
2735 2768 command line.
2736 2769
2737 2770 You can use OpenSSL's CA certificate file if your platform has
2738 2771 one. On most Linux systems this will be
2739 2772 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2740 2773 generate this file manually. The form must be as follows::
2741 2774
2742 2775 -----BEGIN CERTIFICATE-----
2743 2776 ... (certificate in base64 PEM encoding) ...
2744 2777 -----END CERTIFICATE-----
2745 2778 -----BEGIN CERTIFICATE-----
2746 2779 ... (certificate in base64 PEM encoding) ...
2747 2780 -----END CERTIFICATE-----
2748 2781
2749 2782 ``cache``
2750 2783 Whether to support caching in hgweb. (default: True)
2751 2784
2752 2785 ``certificate``
2753 2786 Certificate to use when running :hg:`serve`.
2754 2787
2755 2788 ``collapse``
2756 2789 With ``descend`` enabled, repositories in subdirectories are shown at
2757 2790 a single level alongside repositories in the current path. With
2758 2791 ``collapse`` also enabled, repositories residing at a deeper level than
2759 2792 the current path are grouped behind navigable directory entries that
2760 2793 lead to the locations of these repositories. In effect, this setting
2761 2794 collapses each collection of repositories found within a subdirectory
2762 2795 into a single entry for that subdirectory. (default: False)
2763 2796
2764 2797 ``comparisoncontext``
2765 2798 Number of lines of context to show in side-by-side file comparison. If
2766 2799 negative or the value ``full``, whole files are shown. (default: 5)
2767 2800
2768 2801 This setting can be overridden by a ``context`` request parameter to the
2769 2802 ``comparison`` command, taking the same values.
2770 2803
2771 2804 ``contact``
2772 2805 Name or email address of the person in charge of the repository.
2773 2806 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2774 2807
2775 2808 ``csp``
2776 2809 Send a ``Content-Security-Policy`` HTTP header with this value.
2777 2810
2778 2811 The value may contain a special string ``%nonce%``, which will be replaced
2779 2812 by a randomly-generated one-time use value. If the value contains
2780 2813 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2781 2814 one-time property of the nonce. This nonce will also be inserted into
2782 2815 ``<script>`` elements containing inline JavaScript.
2783 2816
2784 2817 Note: lots of HTML content sent by the server is derived from repository
2785 2818 data. Please consider the potential for malicious repository data to
2786 2819 "inject" itself into generated HTML content as part of your security
2787 2820 threat model.
2788 2821
2789 2822 ``deny_push``
2790 2823 Whether to deny pushing to the repository. If empty or not set,
2791 2824 push is not denied. If the special value ``*``, all remote users are
2792 2825 denied push. Otherwise, unauthenticated users are all denied, and
2793 2826 any authenticated user name present in this list is also denied. The
2794 2827 contents of the deny_push list are examined before the allow-push list.
2795 2828
2796 2829 ``deny_read``
2797 2830 Whether to deny reading/viewing of the repository. If this list is
2798 2831 not empty, unauthenticated users are all denied, and any
2799 2832 authenticated user name present in this list is also denied access to
2800 2833 the repository. If set to the special value ``*``, all remote users
2801 2834 are denied access (rarely needed ;). If deny_read is empty or not set,
2802 2835 the determination of repository access depends on the presence and
2803 2836 content of the allow_read list (see description). If both
2804 2837 deny_read and allow_read are empty or not set, then access is
2805 2838 permitted to all users by default. If the repository is being
2806 2839 served via hgwebdir, denied users will not be able to see it in
2807 2840 the list of repositories. The contents of the deny_read list have
2808 2841 priority over (are examined before) the contents of the allow_read
2809 2842 list.
2810 2843
2811 2844 ``descend``
2812 2845 hgwebdir indexes will not descend into subdirectories. Only repositories
2813 2846 directly in the current path will be shown (other repositories are still
2814 2847 available from the index corresponding to their containing path).
2815 2848
2816 2849 ``description``
2817 2850 Textual description of the repository's purpose or contents.
2818 2851 (default: "unknown")
2819 2852
2820 2853 ``encoding``
2821 2854 Character encoding name. (default: the current locale charset)
2822 2855 Example: "UTF-8".
2823 2856
2824 2857 ``errorlog``
2825 2858 Where to output the error log. (default: stderr)
2826 2859
2827 2860 ``guessmime``
2828 2861 Control MIME types for raw download of file content.
2829 2862 Set to True to let hgweb guess the content type from the file
2830 2863 extension. This will serve HTML files as ``text/html`` and might
2831 2864 allow cross-site scripting attacks when serving untrusted
2832 2865 repositories. (default: False)
2833 2866
2834 2867 ``hidden``
2835 2868 Whether to hide the repository in the hgwebdir index.
2836 2869 (default: False)
2837 2870
2838 2871 ``ipv6``
2839 2872 Whether to use IPv6. (default: False)
2840 2873
2841 2874 ``labels``
2842 2875 List of string *labels* associated with the repository.
2843 2876
2844 2877 Labels are exposed as a template keyword and can be used to customize
2845 2878 output. e.g. the ``index`` template can group or filter repositories
2846 2879 by labels and the ``summary`` template can display additional content
2847 2880 if a specific label is present.
2848 2881
2849 2882 ``logoimg``
2850 2883 File name of the logo image that some templates display on each page.
2851 2884 The file name is relative to ``staticurl``. That is, the full path to
2852 2885 the logo image is "staticurl/logoimg".
2853 2886 If unset, ``hglogo.png`` will be used.
2854 2887
2855 2888 ``logourl``
2856 2889 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2857 2890 will be used.
2858 2891
2859 2892 ``maxchanges``
2860 2893 Maximum number of changes to list on the changelog. (default: 10)
2861 2894
2862 2895 ``maxfiles``
2863 2896 Maximum number of files to list per changeset. (default: 10)
2864 2897
2865 2898 ``maxshortchanges``
2866 2899 Maximum number of changes to list on the shortlog, graph or filelog
2867 2900 pages. (default: 60)
2868 2901
2869 2902 ``name``
2870 2903 Repository name to use in the web interface.
2871 2904 (default: current working directory)
2872 2905
2873 2906 ``port``
2874 2907 Port to listen on. (default: 8000)
2875 2908
2876 2909 ``prefix``
2877 2910 Prefix path to serve from. (default: '' (server root))
2878 2911
2879 2912 ``push_ssl``
2880 2913 Whether to require that inbound pushes be transported over SSL to
2881 2914 prevent password sniffing. (default: True)
2882 2915
2883 2916 ``refreshinterval``
2884 2917 How frequently directory listings re-scan the filesystem for new
2885 2918 repositories, in seconds. This is relevant when wildcards are used
2886 2919 to define paths. Depending on how much filesystem traversal is
2887 2920 required, refreshing may negatively impact performance.
2888 2921
2889 2922 Values less than or equal to 0 always refresh.
2890 2923 (default: 20)
2891 2924
2892 2925 ``server-header``
2893 2926 Value for HTTP ``Server`` response header.
2894 2927
2895 2928 ``static``
2896 2929 Directory where static files are served from.
2897 2930
2898 2931 ``staticurl``
2899 2932 Base URL to use for static files. If unset, static files (e.g. the
2900 2933 hgicon.png favicon) will be served by the CGI script itself. Use
2901 2934 this setting to serve them directly with the HTTP server.
2902 2935 Example: ``http://hgserver/static/``.
2903 2936
2904 2937 ``stripes``
2905 2938 How many lines a "zebra stripe" should span in multi-line output.
2906 2939 Set to 0 to disable. (default: 1)
2907 2940
2908 2941 ``style``
2909 2942 Which template map style to use. The available options are the names of
2910 2943 subdirectories in the HTML templates path. (default: ``paper``)
2911 2944 Example: ``monoblue``.
2912 2945
2913 2946 ``templates``
2914 2947 Where to find the HTML templates. The default path to the HTML templates
2915 2948 can be obtained from ``hg debuginstall``.
2916 2949
2917 2950 ``websub``
2918 2951 ----------
2919 2952
2920 2953 Web substitution filter definition. You can use this section to
2921 2954 define a set of regular expression substitution patterns which
2922 2955 let you automatically modify the hgweb server output.
2923 2956
2924 2957 The default hgweb templates only apply these substitution patterns
2925 2958 on the revision description fields. You can apply them anywhere
2926 2959 you want when you create your own templates by adding calls to the
2927 2960 "websub" filter (usually after calling the "escape" filter).
2928 2961
2929 2962 This can be used, for example, to convert issue references to links
2930 2963 to your issue tracker, or to convert "markdown-like" syntax into
2931 2964 HTML (see the examples below).
2932 2965
2933 2966 Each entry in this section names a substitution filter.
2934 2967 The value of each entry defines the substitution expression itself.
2935 2968 The websub expressions follow the old interhg extension syntax,
2936 2969 which in turn imitates the Unix sed replacement syntax::
2937 2970
2938 2971 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2939 2972
2940 2973 You can use any separator other than "/". The final "i" is optional
2941 2974 and indicates that the search must be case insensitive.
2942 2975
2943 2976 Examples::
2944 2977
2945 2978 [websub]
2946 2979 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2947 2980 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2948 2981 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2949 2982
2950 2983 ``worker``
2951 2984 ----------
2952 2985
2953 2986 Parallel master/worker configuration. We currently perform working
2954 2987 directory updates in parallel on Unix-like systems, which greatly
2955 2988 helps performance.
2956 2989
2957 2990 ``enabled``
2958 2991 Whether to enable workers code to be used.
2959 2992 (default: true)
2960 2993
2961 2994 ``numcpus``
2962 2995 Number of CPUs to use for parallel operations. A zero or
2963 2996 negative value is treated as ``use the default``.
2964 2997 (default: 4 or the number of CPUs on the system, whichever is larger)
2965 2998
2966 2999 ``backgroundclose``
2967 3000 Whether to enable closing file handles on background threads during certain
2968 3001 operations. Some platforms aren't very efficient at closing file
2969 3002 handles that have been written or appended to. By performing file closing
2970 3003 on background threads, file write rate can increase substantially.
2971 3004 (default: true on Windows, false elsewhere)
2972 3005
2973 3006 ``backgroundcloseminfilecount``
2974 3007 Minimum number of files required to trigger background file closing.
2975 3008 Operations not writing this many files won't start background close
2976 3009 threads.
2977 3010 (default: 2048)
2978 3011
2979 3012 ``backgroundclosemaxqueue``
2980 3013 The maximum number of opened file handles waiting to be closed in the
2981 3014 background. This option only has an effect if ``backgroundclose`` is
2982 3015 enabled.
2983 3016 (default: 384)
2984 3017
2985 3018 ``backgroundclosethreadcount``
2986 3019 Number of threads to process background file closes. Only relevant if
2987 3020 ``backgroundclose`` is enabled.
2988 3021 (default: 4)
@@ -1,3649 +1,3684 b''
1 1 # localrepo.py - read/write repository class for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
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 errno
11 11 import functools
12 12 import os
13 13 import random
14 14 import sys
15 15 import time
16 16 import weakref
17 17
18 18 from .i18n import _
19 19 from .node import (
20 20 bin,
21 21 hex,
22 22 nullid,
23 23 nullrev,
24 24 short,
25 25 )
26 26 from .pycompat import (
27 27 delattr,
28 28 getattr,
29 29 )
30 30 from . import (
31 31 bookmarks,
32 32 branchmap,
33 33 bundle2,
34 34 bundlecaches,
35 35 changegroup,
36 36 color,
37 37 commit,
38 38 context,
39 39 dirstate,
40 40 dirstateguard,
41 41 discovery,
42 42 encoding,
43 43 error,
44 44 exchange,
45 45 extensions,
46 46 filelog,
47 47 hook,
48 48 lock as lockmod,
49 49 match as matchmod,
50 50 mergestate as mergestatemod,
51 51 mergeutil,
52 52 namespaces,
53 53 narrowspec,
54 54 obsolete,
55 55 pathutil,
56 56 phases,
57 57 pushkey,
58 58 pycompat,
59 59 rcutil,
60 60 repoview,
61 61 requirements as requirementsmod,
62 62 revlog,
63 63 revset,
64 64 revsetlang,
65 65 scmutil,
66 66 sparse,
67 67 store as storemod,
68 68 subrepoutil,
69 69 tags as tagsmod,
70 70 transaction,
71 71 txnutil,
72 72 util,
73 73 vfs as vfsmod,
74 74 )
75 75
76 76 from .interfaces import (
77 77 repository,
78 78 util as interfaceutil,
79 79 )
80 80
81 81 from .utils import (
82 82 hashutil,
83 83 procutil,
84 84 stringutil,
85 85 )
86 86
87 87 from .revlogutils import constants as revlogconst
88 88
89 89 release = lockmod.release
90 90 urlerr = util.urlerr
91 91 urlreq = util.urlreq
92 92
93 93 # set of (path, vfs-location) tuples. vfs-location is:
94 94 # - 'plain for vfs relative paths
95 95 # - '' for svfs relative paths
96 96 _cachedfiles = set()
97 97
98 98
99 99 class _basefilecache(scmutil.filecache):
100 100 """All filecache usage on repo are done for logic that should be unfiltered"""
101 101
102 102 def __get__(self, repo, type=None):
103 103 if repo is None:
104 104 return self
105 105 # proxy to unfiltered __dict__ since filtered repo has no entry
106 106 unfi = repo.unfiltered()
107 107 try:
108 108 return unfi.__dict__[self.sname]
109 109 except KeyError:
110 110 pass
111 111 return super(_basefilecache, self).__get__(unfi, type)
112 112
113 113 def set(self, repo, value):
114 114 return super(_basefilecache, self).set(repo.unfiltered(), value)
115 115
116 116
117 117 class repofilecache(_basefilecache):
118 118 """filecache for files in .hg but outside of .hg/store"""
119 119
120 120 def __init__(self, *paths):
121 121 super(repofilecache, self).__init__(*paths)
122 122 for path in paths:
123 123 _cachedfiles.add((path, b'plain'))
124 124
125 125 def join(self, obj, fname):
126 126 return obj.vfs.join(fname)
127 127
128 128
129 129 class storecache(_basefilecache):
130 130 """filecache for files in the store"""
131 131
132 132 def __init__(self, *paths):
133 133 super(storecache, self).__init__(*paths)
134 134 for path in paths:
135 135 _cachedfiles.add((path, b''))
136 136
137 137 def join(self, obj, fname):
138 138 return obj.sjoin(fname)
139 139
140 140
141 141 class mixedrepostorecache(_basefilecache):
142 142 """filecache for a mix files in .hg/store and outside"""
143 143
144 144 def __init__(self, *pathsandlocations):
145 145 # scmutil.filecache only uses the path for passing back into our
146 146 # join(), so we can safely pass a list of paths and locations
147 147 super(mixedrepostorecache, self).__init__(*pathsandlocations)
148 148 _cachedfiles.update(pathsandlocations)
149 149
150 150 def join(self, obj, fnameandlocation):
151 151 fname, location = fnameandlocation
152 152 if location == b'plain':
153 153 return obj.vfs.join(fname)
154 154 else:
155 155 if location != b'':
156 156 raise error.ProgrammingError(
157 157 b'unexpected location: %s' % location
158 158 )
159 159 return obj.sjoin(fname)
160 160
161 161
162 162 def isfilecached(repo, name):
163 163 """check if a repo has already cached "name" filecache-ed property
164 164
165 165 This returns (cachedobj-or-None, iscached) tuple.
166 166 """
167 167 cacheentry = repo.unfiltered()._filecache.get(name, None)
168 168 if not cacheentry:
169 169 return None, False
170 170 return cacheentry.obj, True
171 171
172 172
173 173 class unfilteredpropertycache(util.propertycache):
174 174 """propertycache that apply to unfiltered repo only"""
175 175
176 176 def __get__(self, repo, type=None):
177 177 unfi = repo.unfiltered()
178 178 if unfi is repo:
179 179 return super(unfilteredpropertycache, self).__get__(unfi)
180 180 return getattr(unfi, self.name)
181 181
182 182
183 183 class filteredpropertycache(util.propertycache):
184 184 """propertycache that must take filtering in account"""
185 185
186 186 def cachevalue(self, obj, value):
187 187 object.__setattr__(obj, self.name, value)
188 188
189 189
190 190 def hasunfilteredcache(repo, name):
191 191 """check if a repo has an unfilteredpropertycache value for <name>"""
192 192 return name in vars(repo.unfiltered())
193 193
194 194
195 195 def unfilteredmethod(orig):
196 196 """decorate method that always need to be run on unfiltered version"""
197 197
198 198 @functools.wraps(orig)
199 199 def wrapper(repo, *args, **kwargs):
200 200 return orig(repo.unfiltered(), *args, **kwargs)
201 201
202 202 return wrapper
203 203
204 204
205 205 moderncaps = {
206 206 b'lookup',
207 207 b'branchmap',
208 208 b'pushkey',
209 209 b'known',
210 210 b'getbundle',
211 211 b'unbundle',
212 212 }
213 213 legacycaps = moderncaps.union({b'changegroupsubset'})
214 214
215 215
216 216 @interfaceutil.implementer(repository.ipeercommandexecutor)
217 217 class localcommandexecutor(object):
218 218 def __init__(self, peer):
219 219 self._peer = peer
220 220 self._sent = False
221 221 self._closed = False
222 222
223 223 def __enter__(self):
224 224 return self
225 225
226 226 def __exit__(self, exctype, excvalue, exctb):
227 227 self.close()
228 228
229 229 def callcommand(self, command, args):
230 230 if self._sent:
231 231 raise error.ProgrammingError(
232 232 b'callcommand() cannot be used after sendcommands()'
233 233 )
234 234
235 235 if self._closed:
236 236 raise error.ProgrammingError(
237 237 b'callcommand() cannot be used after close()'
238 238 )
239 239
240 240 # We don't need to support anything fancy. Just call the named
241 241 # method on the peer and return a resolved future.
242 242 fn = getattr(self._peer, pycompat.sysstr(command))
243 243
244 244 f = pycompat.futures.Future()
245 245
246 246 try:
247 247 result = fn(**pycompat.strkwargs(args))
248 248 except Exception:
249 249 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
250 250 else:
251 251 f.set_result(result)
252 252
253 253 return f
254 254
255 255 def sendcommands(self):
256 256 self._sent = True
257 257
258 258 def close(self):
259 259 self._closed = True
260 260
261 261
262 262 @interfaceutil.implementer(repository.ipeercommands)
263 263 class localpeer(repository.peer):
264 264 '''peer for a local repo; reflects only the most recent API'''
265 265
266 266 def __init__(self, repo, caps=None):
267 267 super(localpeer, self).__init__()
268 268
269 269 if caps is None:
270 270 caps = moderncaps.copy()
271 271 self._repo = repo.filtered(b'served')
272 272 self.ui = repo.ui
273 273 self._caps = repo._restrictcapabilities(caps)
274 274
275 275 # Begin of _basepeer interface.
276 276
277 277 def url(self):
278 278 return self._repo.url()
279 279
280 280 def local(self):
281 281 return self._repo
282 282
283 283 def peer(self):
284 284 return self
285 285
286 286 def canpush(self):
287 287 return True
288 288
289 289 def close(self):
290 290 self._repo.close()
291 291
292 292 # End of _basepeer interface.
293 293
294 294 # Begin of _basewirecommands interface.
295 295
296 296 def branchmap(self):
297 297 return self._repo.branchmap()
298 298
299 299 def capabilities(self):
300 300 return self._caps
301 301
302 302 def clonebundles(self):
303 303 return self._repo.tryread(bundlecaches.CB_MANIFEST_FILE)
304 304
305 305 def debugwireargs(self, one, two, three=None, four=None, five=None):
306 306 """Used to test argument passing over the wire"""
307 307 return b"%s %s %s %s %s" % (
308 308 one,
309 309 two,
310 310 pycompat.bytestr(three),
311 311 pycompat.bytestr(four),
312 312 pycompat.bytestr(five),
313 313 )
314 314
315 315 def getbundle(
316 316 self, source, heads=None, common=None, bundlecaps=None, **kwargs
317 317 ):
318 318 chunks = exchange.getbundlechunks(
319 319 self._repo,
320 320 source,
321 321 heads=heads,
322 322 common=common,
323 323 bundlecaps=bundlecaps,
324 324 **kwargs
325 325 )[1]
326 326 cb = util.chunkbuffer(chunks)
327 327
328 328 if exchange.bundle2requested(bundlecaps):
329 329 # When requesting a bundle2, getbundle returns a stream to make the
330 330 # wire level function happier. We need to build a proper object
331 331 # from it in local peer.
332 332 return bundle2.getunbundler(self.ui, cb)
333 333 else:
334 334 return changegroup.getunbundler(b'01', cb, None)
335 335
336 336 def heads(self):
337 337 return self._repo.heads()
338 338
339 339 def known(self, nodes):
340 340 return self._repo.known(nodes)
341 341
342 342 def listkeys(self, namespace):
343 343 return self._repo.listkeys(namespace)
344 344
345 345 def lookup(self, key):
346 346 return self._repo.lookup(key)
347 347
348 348 def pushkey(self, namespace, key, old, new):
349 349 return self._repo.pushkey(namespace, key, old, new)
350 350
351 351 def stream_out(self):
352 352 raise error.Abort(_(b'cannot perform stream clone against local peer'))
353 353
354 354 def unbundle(self, bundle, heads, url):
355 355 """apply a bundle on a repo
356 356
357 357 This function handles the repo locking itself."""
358 358 try:
359 359 try:
360 360 bundle = exchange.readbundle(self.ui, bundle, None)
361 361 ret = exchange.unbundle(self._repo, bundle, heads, b'push', url)
362 362 if util.safehasattr(ret, b'getchunks'):
363 363 # This is a bundle20 object, turn it into an unbundler.
364 364 # This little dance should be dropped eventually when the
365 365 # API is finally improved.
366 366 stream = util.chunkbuffer(ret.getchunks())
367 367 ret = bundle2.getunbundler(self.ui, stream)
368 368 return ret
369 369 except Exception as exc:
370 370 # If the exception contains output salvaged from a bundle2
371 371 # reply, we need to make sure it is printed before continuing
372 372 # to fail. So we build a bundle2 with such output and consume
373 373 # it directly.
374 374 #
375 375 # This is not very elegant but allows a "simple" solution for
376 376 # issue4594
377 377 output = getattr(exc, '_bundle2salvagedoutput', ())
378 378 if output:
379 379 bundler = bundle2.bundle20(self._repo.ui)
380 380 for out in output:
381 381 bundler.addpart(out)
382 382 stream = util.chunkbuffer(bundler.getchunks())
383 383 b = bundle2.getunbundler(self.ui, stream)
384 384 bundle2.processbundle(self._repo, b)
385 385 raise
386 386 except error.PushRaced as exc:
387 387 raise error.ResponseError(
388 388 _(b'push failed:'), stringutil.forcebytestr(exc)
389 389 )
390 390
391 391 # End of _basewirecommands interface.
392 392
393 393 # Begin of peer interface.
394 394
395 395 def commandexecutor(self):
396 396 return localcommandexecutor(self)
397 397
398 398 # End of peer interface.
399 399
400 400
401 401 @interfaceutil.implementer(repository.ipeerlegacycommands)
402 402 class locallegacypeer(localpeer):
403 403 """peer extension which implements legacy methods too; used for tests with
404 404 restricted capabilities"""
405 405
406 406 def __init__(self, repo):
407 407 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
408 408
409 409 # Begin of baselegacywirecommands interface.
410 410
411 411 def between(self, pairs):
412 412 return self._repo.between(pairs)
413 413
414 414 def branches(self, nodes):
415 415 return self._repo.branches(nodes)
416 416
417 417 def changegroup(self, nodes, source):
418 418 outgoing = discovery.outgoing(
419 419 self._repo, missingroots=nodes, ancestorsof=self._repo.heads()
420 420 )
421 421 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
422 422
423 423 def changegroupsubset(self, bases, heads, source):
424 424 outgoing = discovery.outgoing(
425 425 self._repo, missingroots=bases, ancestorsof=heads
426 426 )
427 427 return changegroup.makechangegroup(self._repo, outgoing, b'01', source)
428 428
429 429 # End of baselegacywirecommands interface.
430 430
431 431
432 432 # Functions receiving (ui, features) that extensions can register to impact
433 433 # the ability to load repositories with custom requirements. Only
434 434 # functions defined in loaded extensions are called.
435 435 #
436 436 # The function receives a set of requirement strings that the repository
437 437 # is capable of opening. Functions will typically add elements to the
438 438 # set to reflect that the extension knows how to handle that requirements.
439 439 featuresetupfuncs = set()
440 440
441 441
442 442 def _getsharedvfs(hgvfs, requirements):
443 443 """returns the vfs object pointing to root of shared source
444 444 repo for a shared repository
445 445
446 446 hgvfs is vfs pointing at .hg/ of current repo (shared one)
447 447 requirements is a set of requirements of current repo (shared one)
448 448 """
449 449 # The ``shared`` or ``relshared`` requirements indicate the
450 450 # store lives in the path contained in the ``.hg/sharedpath`` file.
451 451 # This is an absolute path for ``shared`` and relative to
452 452 # ``.hg/`` for ``relshared``.
453 453 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
454 454 if requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements:
455 455 sharedpath = hgvfs.join(sharedpath)
456 456
457 457 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
458 458
459 459 if not sharedvfs.exists():
460 460 raise error.RepoError(
461 461 _(b'.hg/sharedpath points to nonexistent directory %s')
462 462 % sharedvfs.base
463 463 )
464 464 return sharedvfs
465 465
466 466
467 467 def _readrequires(vfs, allowmissing):
468 468 """reads the require file present at root of this vfs
469 469 and return a set of requirements
470 470
471 471 If allowmissing is True, we suppress ENOENT if raised"""
472 472 # requires file contains a newline-delimited list of
473 473 # features/capabilities the opener (us) must have in order to use
474 474 # the repository. This file was introduced in Mercurial 0.9.2,
475 475 # which means very old repositories may not have one. We assume
476 476 # a missing file translates to no requirements.
477 477 try:
478 478 requirements = set(vfs.read(b'requires').splitlines())
479 479 except IOError as e:
480 480 if not (allowmissing and e.errno == errno.ENOENT):
481 481 raise
482 482 requirements = set()
483 483 return requirements
484 484
485 485
486 486 def makelocalrepository(baseui, path, intents=None):
487 487 """Create a local repository object.
488 488
489 489 Given arguments needed to construct a local repository, this function
490 490 performs various early repository loading functionality (such as
491 491 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
492 492 the repository can be opened, derives a type suitable for representing
493 493 that repository, and returns an instance of it.
494 494
495 495 The returned object conforms to the ``repository.completelocalrepository``
496 496 interface.
497 497
498 498 The repository type is derived by calling a series of factory functions
499 499 for each aspect/interface of the final repository. These are defined by
500 500 ``REPO_INTERFACES``.
501 501
502 502 Each factory function is called to produce a type implementing a specific
503 503 interface. The cumulative list of returned types will be combined into a
504 504 new type and that type will be instantiated to represent the local
505 505 repository.
506 506
507 507 The factory functions each receive various state that may be consulted
508 508 as part of deriving a type.
509 509
510 510 Extensions should wrap these factory functions to customize repository type
511 511 creation. Note that an extension's wrapped function may be called even if
512 512 that extension is not loaded for the repo being constructed. Extensions
513 513 should check if their ``__name__`` appears in the
514 514 ``extensionmodulenames`` set passed to the factory function and no-op if
515 515 not.
516 516 """
517 517 ui = baseui.copy()
518 518 # Prevent copying repo configuration.
519 519 ui.copy = baseui.copy
520 520
521 521 # Working directory VFS rooted at repository root.
522 522 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
523 523
524 524 # Main VFS for .hg/ directory.
525 525 hgpath = wdirvfs.join(b'.hg')
526 526 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
527 527 # Whether this repository is shared one or not
528 528 shared = False
529 529 # If this repository is shared, vfs pointing to shared repo
530 530 sharedvfs = None
531 531
532 532 # The .hg/ path should exist and should be a directory. All other
533 533 # cases are errors.
534 534 if not hgvfs.isdir():
535 535 try:
536 536 hgvfs.stat()
537 537 except OSError as e:
538 538 if e.errno != errno.ENOENT:
539 539 raise
540 540 except ValueError as e:
541 541 # Can be raised on Python 3.8 when path is invalid.
542 542 raise error.Abort(
543 543 _(b'invalid path %s: %s') % (path, pycompat.bytestr(e))
544 544 )
545 545
546 546 raise error.RepoError(_(b'repository %s not found') % path)
547 547
548 548 requirements = _readrequires(hgvfs, True)
549 549 shared = (
550 550 requirementsmod.SHARED_REQUIREMENT in requirements
551 551 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
552 552 )
553 553 storevfs = None
554 554 if shared:
555 555 # This is a shared repo
556 556 sharedvfs = _getsharedvfs(hgvfs, requirements)
557 557 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
558 558 else:
559 559 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
560 560
561 561 # if .hg/requires contains the sharesafe requirement, it means
562 562 # there exists a `.hg/store/requires` too and we should read it
563 563 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
564 564 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
565 565 # is not present, refer checkrequirementscompat() for that
566 566 #
567 567 # However, if SHARESAFE_REQUIREMENT is not present, it means that the
568 568 # repository was shared the old way. We check the share source .hg/requires
569 569 # for SHARESAFE_REQUIREMENT to detect whether the current repository needs
570 570 # to be reshared
571 571 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
572 572
573 573 if (
574 574 shared
575 575 and requirementsmod.SHARESAFE_REQUIREMENT
576 576 not in _readrequires(sharedvfs, True)
577 577 ):
578 if ui.configbool(
579 b'experimental', b'sharesafe-auto-downgrade-shares'
578 mismatch_config = ui.config(
579 b'share', b'safe-mismatch.source-not-safe'
580 )
581 if mismatch_config in (
582 b'downgrade-allow',
583 b'allow',
584 b'downgrade-abort',
580 585 ):
581 586 # prevent cyclic import localrepo -> upgrade -> localrepo
582 587 from . import upgrade
583 588
584 589 upgrade.downgrade_share_to_non_safe(
585 590 ui,
586 591 hgvfs,
587 592 sharedvfs,
588 593 requirements,
594 mismatch_config,
589 595 )
590 else:
596 elif mismatch_config == b'abort':
591 597 raise error.Abort(
592 598 _(
593 599 b"share source does not support exp-sharesafe requirement"
594 600 )
595 601 )
602 else:
603 hint = _(
604 "run `hg help config.share.safe-mismatch.source-not-safe`"
605 )
606 raise error.Abort(
607 _(
608 b"share-safe mismatch with source.\nUnrecognized"
609 b" value '%s' of `share.safe-mismatch.source-not-safe`"
610 b" set."
611 )
612 % mismatch_config,
613 hint=hint,
614 )
596 615 else:
597 616 requirements |= _readrequires(storevfs, False)
598 617 elif shared:
599 618 sourcerequires = _readrequires(sharedvfs, False)
600 619 if requirementsmod.SHARESAFE_REQUIREMENT in sourcerequires:
601 if ui.configbool(b'experimental', b'sharesafe-auto-upgrade-shares'):
620 mismatch_config = ui.config(b'share', b'safe-mismatch.source-safe')
621 if mismatch_config in (
622 b'upgrade-allow',
623 b'allow',
624 b'upgrade-abort',
625 ):
602 626 # prevent cyclic import localrepo -> upgrade -> localrepo
603 627 from . import upgrade
604 628
605 629 upgrade.upgrade_share_to_safe(
606 630 ui,
607 631 hgvfs,
608 632 storevfs,
609 633 requirements,
634 mismatch_config,
610 635 )
611 else:
636 elif mismatch_config == b'abort':
612 637 raise error.Abort(
613 638 _(
614 639 b'version mismatch: source uses share-safe'
615 640 b' functionality while the current share does not'
616 641 )
617 642 )
643 else:
644 hint = _("run `hg help config.share.safe-mismatch.source-safe`")
645 raise error.Abort(
646 _(
647 b"share-safe mismatch with source.\nUnrecognized"
648 b" value '%s' of `share.safe-mismatch.source-safe` set."
649 )
650 % mismatch_config,
651 hint=hint,
652 )
618 653
619 654 # The .hg/hgrc file may load extensions or contain config options
620 655 # that influence repository construction. Attempt to load it and
621 656 # process any new extensions that it may have pulled in.
622 657 if loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs):
623 658 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
624 659 extensions.loadall(ui)
625 660 extensions.populateui(ui)
626 661
627 662 # Set of module names of extensions loaded for this repository.
628 663 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
629 664
630 665 supportedrequirements = gathersupportedrequirements(ui)
631 666
632 667 # We first validate the requirements are known.
633 668 ensurerequirementsrecognized(requirements, supportedrequirements)
634 669
635 670 # Then we validate that the known set is reasonable to use together.
636 671 ensurerequirementscompatible(ui, requirements)
637 672
638 673 # TODO there are unhandled edge cases related to opening repositories with
639 674 # shared storage. If storage is shared, we should also test for requirements
640 675 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
641 676 # that repo, as that repo may load extensions needed to open it. This is a
642 677 # bit complicated because we don't want the other hgrc to overwrite settings
643 678 # in this hgrc.
644 679 #
645 680 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
646 681 # file when sharing repos. But if a requirement is added after the share is
647 682 # performed, thereby introducing a new requirement for the opener, we may
648 683 # will not see that and could encounter a run-time error interacting with
649 684 # that shared store since it has an unknown-to-us requirement.
650 685
651 686 # At this point, we know we should be capable of opening the repository.
652 687 # Now get on with doing that.
653 688
654 689 features = set()
655 690
656 691 # The "store" part of the repository holds versioned data. How it is
657 692 # accessed is determined by various requirements. If `shared` or
658 693 # `relshared` requirements are present, this indicates current repository
659 694 # is a share and store exists in path mentioned in `.hg/sharedpath`
660 695 if shared:
661 696 storebasepath = sharedvfs.base
662 697 cachepath = sharedvfs.join(b'cache')
663 698 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
664 699 else:
665 700 storebasepath = hgvfs.base
666 701 cachepath = hgvfs.join(b'cache')
667 702 wcachepath = hgvfs.join(b'wcache')
668 703
669 704 # The store has changed over time and the exact layout is dictated by
670 705 # requirements. The store interface abstracts differences across all
671 706 # of them.
672 707 store = makestore(
673 708 requirements,
674 709 storebasepath,
675 710 lambda base: vfsmod.vfs(base, cacheaudited=True),
676 711 )
677 712 hgvfs.createmode = store.createmode
678 713
679 714 storevfs = store.vfs
680 715 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
681 716
682 717 # The cache vfs is used to manage cache files.
683 718 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
684 719 cachevfs.createmode = store.createmode
685 720 # The cache vfs is used to manage cache files related to the working copy
686 721 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
687 722 wcachevfs.createmode = store.createmode
688 723
689 724 # Now resolve the type for the repository object. We do this by repeatedly
690 725 # calling a factory function to produces types for specific aspects of the
691 726 # repo's operation. The aggregate returned types are used as base classes
692 727 # for a dynamically-derived type, which will represent our new repository.
693 728
694 729 bases = []
695 730 extrastate = {}
696 731
697 732 for iface, fn in REPO_INTERFACES:
698 733 # We pass all potentially useful state to give extensions tons of
699 734 # flexibility.
700 735 typ = fn()(
701 736 ui=ui,
702 737 intents=intents,
703 738 requirements=requirements,
704 739 features=features,
705 740 wdirvfs=wdirvfs,
706 741 hgvfs=hgvfs,
707 742 store=store,
708 743 storevfs=storevfs,
709 744 storeoptions=storevfs.options,
710 745 cachevfs=cachevfs,
711 746 wcachevfs=wcachevfs,
712 747 extensionmodulenames=extensionmodulenames,
713 748 extrastate=extrastate,
714 749 baseclasses=bases,
715 750 )
716 751
717 752 if not isinstance(typ, type):
718 753 raise error.ProgrammingError(
719 754 b'unable to construct type for %s' % iface
720 755 )
721 756
722 757 bases.append(typ)
723 758
724 759 # type() allows you to use characters in type names that wouldn't be
725 760 # recognized as Python symbols in source code. We abuse that to add
726 761 # rich information about our constructed repo.
727 762 name = pycompat.sysstr(
728 763 b'derivedrepo:%s<%s>' % (wdirvfs.base, b','.join(sorted(requirements)))
729 764 )
730 765
731 766 cls = type(name, tuple(bases), {})
732 767
733 768 return cls(
734 769 baseui=baseui,
735 770 ui=ui,
736 771 origroot=path,
737 772 wdirvfs=wdirvfs,
738 773 hgvfs=hgvfs,
739 774 requirements=requirements,
740 775 supportedrequirements=supportedrequirements,
741 776 sharedpath=storebasepath,
742 777 store=store,
743 778 cachevfs=cachevfs,
744 779 wcachevfs=wcachevfs,
745 780 features=features,
746 781 intents=intents,
747 782 )
748 783
749 784
750 785 def loadhgrc(ui, wdirvfs, hgvfs, requirements, sharedvfs=None):
751 786 """Load hgrc files/content into a ui instance.
752 787
753 788 This is called during repository opening to load any additional
754 789 config files or settings relevant to the current repository.
755 790
756 791 Returns a bool indicating whether any additional configs were loaded.
757 792
758 793 Extensions should monkeypatch this function to modify how per-repo
759 794 configs are loaded. For example, an extension may wish to pull in
760 795 configs from alternate files or sources.
761 796
762 797 sharedvfs is vfs object pointing to source repo if the current one is a
763 798 shared one
764 799 """
765 800 if not rcutil.use_repo_hgrc():
766 801 return False
767 802
768 803 ret = False
769 804 # first load config from shared source if we has to
770 805 if requirementsmod.SHARESAFE_REQUIREMENT in requirements and sharedvfs:
771 806 try:
772 807 ui.readconfig(sharedvfs.join(b'hgrc'), root=sharedvfs.base)
773 808 ret = True
774 809 except IOError:
775 810 pass
776 811
777 812 try:
778 813 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
779 814 ret = True
780 815 except IOError:
781 816 pass
782 817
783 818 try:
784 819 ui.readconfig(hgvfs.join(b'hgrc-not-shared'), root=wdirvfs.base)
785 820 ret = True
786 821 except IOError:
787 822 pass
788 823
789 824 return ret
790 825
791 826
792 827 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
793 828 """Perform additional actions after .hg/hgrc is loaded.
794 829
795 830 This function is called during repository loading immediately after
796 831 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
797 832
798 833 The function can be used to validate configs, automatically add
799 834 options (including extensions) based on requirements, etc.
800 835 """
801 836
802 837 # Map of requirements to list of extensions to load automatically when
803 838 # requirement is present.
804 839 autoextensions = {
805 840 b'git': [b'git'],
806 841 b'largefiles': [b'largefiles'],
807 842 b'lfs': [b'lfs'],
808 843 }
809 844
810 845 for requirement, names in sorted(autoextensions.items()):
811 846 if requirement not in requirements:
812 847 continue
813 848
814 849 for name in names:
815 850 if not ui.hasconfig(b'extensions', name):
816 851 ui.setconfig(b'extensions', name, b'', source=b'autoload')
817 852
818 853
819 854 def gathersupportedrequirements(ui):
820 855 """Determine the complete set of recognized requirements."""
821 856 # Start with all requirements supported by this file.
822 857 supported = set(localrepository._basesupported)
823 858
824 859 # Execute ``featuresetupfuncs`` entries if they belong to an extension
825 860 # relevant to this ui instance.
826 861 modules = {m.__name__ for n, m in extensions.extensions(ui)}
827 862
828 863 for fn in featuresetupfuncs:
829 864 if fn.__module__ in modules:
830 865 fn(ui, supported)
831 866
832 867 # Add derived requirements from registered compression engines.
833 868 for name in util.compengines:
834 869 engine = util.compengines[name]
835 870 if engine.available() and engine.revlogheader():
836 871 supported.add(b'exp-compression-%s' % name)
837 872 if engine.name() == b'zstd':
838 873 supported.add(b'revlog-compression-zstd')
839 874
840 875 return supported
841 876
842 877
843 878 def ensurerequirementsrecognized(requirements, supported):
844 879 """Validate that a set of local requirements is recognized.
845 880
846 881 Receives a set of requirements. Raises an ``error.RepoError`` if there
847 882 exists any requirement in that set that currently loaded code doesn't
848 883 recognize.
849 884
850 885 Returns a set of supported requirements.
851 886 """
852 887 missing = set()
853 888
854 889 for requirement in requirements:
855 890 if requirement in supported:
856 891 continue
857 892
858 893 if not requirement or not requirement[0:1].isalnum():
859 894 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
860 895
861 896 missing.add(requirement)
862 897
863 898 if missing:
864 899 raise error.RequirementError(
865 900 _(b'repository requires features unknown to this Mercurial: %s')
866 901 % b' '.join(sorted(missing)),
867 902 hint=_(
868 903 b'see https://mercurial-scm.org/wiki/MissingRequirement '
869 904 b'for more information'
870 905 ),
871 906 )
872 907
873 908
874 909 def ensurerequirementscompatible(ui, requirements):
875 910 """Validates that a set of recognized requirements is mutually compatible.
876 911
877 912 Some requirements may not be compatible with others or require
878 913 config options that aren't enabled. This function is called during
879 914 repository opening to ensure that the set of requirements needed
880 915 to open a repository is sane and compatible with config options.
881 916
882 917 Extensions can monkeypatch this function to perform additional
883 918 checking.
884 919
885 920 ``error.RepoError`` should be raised on failure.
886 921 """
887 922 if (
888 923 requirementsmod.SPARSE_REQUIREMENT in requirements
889 924 and not sparse.enabled
890 925 ):
891 926 raise error.RepoError(
892 927 _(
893 928 b'repository is using sparse feature but '
894 929 b'sparse is not enabled; enable the '
895 930 b'"sparse" extensions to access'
896 931 )
897 932 )
898 933
899 934
900 935 def makestore(requirements, path, vfstype):
901 936 """Construct a storage object for a repository."""
902 937 if b'store' in requirements:
903 938 if b'fncache' in requirements:
904 939 return storemod.fncachestore(
905 940 path, vfstype, b'dotencode' in requirements
906 941 )
907 942
908 943 return storemod.encodedstore(path, vfstype)
909 944
910 945 return storemod.basicstore(path, vfstype)
911 946
912 947
913 948 def resolvestorevfsoptions(ui, requirements, features):
914 949 """Resolve the options to pass to the store vfs opener.
915 950
916 951 The returned dict is used to influence behavior of the storage layer.
917 952 """
918 953 options = {}
919 954
920 955 if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
921 956 options[b'treemanifest'] = True
922 957
923 958 # experimental config: format.manifestcachesize
924 959 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
925 960 if manifestcachesize is not None:
926 961 options[b'manifestcachesize'] = manifestcachesize
927 962
928 963 # In the absence of another requirement superseding a revlog-related
929 964 # requirement, we have to assume the repo is using revlog version 0.
930 965 # This revlog format is super old and we don't bother trying to parse
931 966 # opener options for it because those options wouldn't do anything
932 967 # meaningful on such old repos.
933 968 if (
934 969 b'revlogv1' in requirements
935 970 or requirementsmod.REVLOGV2_REQUIREMENT in requirements
936 971 ):
937 972 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
938 973 else: # explicitly mark repo as using revlogv0
939 974 options[b'revlogv0'] = True
940 975
941 976 if requirementsmod.COPIESSDC_REQUIREMENT in requirements:
942 977 options[b'copies-storage'] = b'changeset-sidedata'
943 978 else:
944 979 writecopiesto = ui.config(b'experimental', b'copies.write-to')
945 980 copiesextramode = (b'changeset-only', b'compatibility')
946 981 if writecopiesto in copiesextramode:
947 982 options[b'copies-storage'] = b'extra'
948 983
949 984 return options
950 985
951 986
952 987 def resolverevlogstorevfsoptions(ui, requirements, features):
953 988 """Resolve opener options specific to revlogs."""
954 989
955 990 options = {}
956 991 options[b'flagprocessors'] = {}
957 992
958 993 if b'revlogv1' in requirements:
959 994 options[b'revlogv1'] = True
960 995 if requirementsmod.REVLOGV2_REQUIREMENT in requirements:
961 996 options[b'revlogv2'] = True
962 997
963 998 if b'generaldelta' in requirements:
964 999 options[b'generaldelta'] = True
965 1000
966 1001 # experimental config: format.chunkcachesize
967 1002 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
968 1003 if chunkcachesize is not None:
969 1004 options[b'chunkcachesize'] = chunkcachesize
970 1005
971 1006 deltabothparents = ui.configbool(
972 1007 b'storage', b'revlog.optimize-delta-parent-choice'
973 1008 )
974 1009 options[b'deltabothparents'] = deltabothparents
975 1010
976 1011 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
977 1012 lazydeltabase = False
978 1013 if lazydelta:
979 1014 lazydeltabase = ui.configbool(
980 1015 b'storage', b'revlog.reuse-external-delta-parent'
981 1016 )
982 1017 if lazydeltabase is None:
983 1018 lazydeltabase = not scmutil.gddeltaconfig(ui)
984 1019 options[b'lazydelta'] = lazydelta
985 1020 options[b'lazydeltabase'] = lazydeltabase
986 1021
987 1022 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
988 1023 if 0 <= chainspan:
989 1024 options[b'maxdeltachainspan'] = chainspan
990 1025
991 1026 mmapindexthreshold = ui.configbytes(b'experimental', b'mmapindexthreshold')
992 1027 if mmapindexthreshold is not None:
993 1028 options[b'mmapindexthreshold'] = mmapindexthreshold
994 1029
995 1030 withsparseread = ui.configbool(b'experimental', b'sparse-read')
996 1031 srdensitythres = float(
997 1032 ui.config(b'experimental', b'sparse-read.density-threshold')
998 1033 )
999 1034 srmingapsize = ui.configbytes(b'experimental', b'sparse-read.min-gap-size')
1000 1035 options[b'with-sparse-read'] = withsparseread
1001 1036 options[b'sparse-read-density-threshold'] = srdensitythres
1002 1037 options[b'sparse-read-min-gap-size'] = srmingapsize
1003 1038
1004 1039 sparserevlog = requirementsmod.SPARSEREVLOG_REQUIREMENT in requirements
1005 1040 options[b'sparse-revlog'] = sparserevlog
1006 1041 if sparserevlog:
1007 1042 options[b'generaldelta'] = True
1008 1043
1009 1044 sidedata = requirementsmod.SIDEDATA_REQUIREMENT in requirements
1010 1045 options[b'side-data'] = sidedata
1011 1046
1012 1047 maxchainlen = None
1013 1048 if sparserevlog:
1014 1049 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
1015 1050 # experimental config: format.maxchainlen
1016 1051 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
1017 1052 if maxchainlen is not None:
1018 1053 options[b'maxchainlen'] = maxchainlen
1019 1054
1020 1055 for r in requirements:
1021 1056 # we allow multiple compression engine requirement to co-exist because
1022 1057 # strickly speaking, revlog seems to support mixed compression style.
1023 1058 #
1024 1059 # The compression used for new entries will be "the last one"
1025 1060 prefix = r.startswith
1026 1061 if prefix(b'revlog-compression-') or prefix(b'exp-compression-'):
1027 1062 options[b'compengine'] = r.split(b'-', 2)[2]
1028 1063
1029 1064 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
1030 1065 if options[b'zlib.level'] is not None:
1031 1066 if not (0 <= options[b'zlib.level'] <= 9):
1032 1067 msg = _(b'invalid value for `storage.revlog.zlib.level` config: %d')
1033 1068 raise error.Abort(msg % options[b'zlib.level'])
1034 1069 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
1035 1070 if options[b'zstd.level'] is not None:
1036 1071 if not (0 <= options[b'zstd.level'] <= 22):
1037 1072 msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
1038 1073 raise error.Abort(msg % options[b'zstd.level'])
1039 1074
1040 1075 if requirementsmod.NARROW_REQUIREMENT in requirements:
1041 1076 options[b'enableellipsis'] = True
1042 1077
1043 1078 if ui.configbool(b'experimental', b'rust.index'):
1044 1079 options[b'rust.index'] = True
1045 1080 if requirementsmod.NODEMAP_REQUIREMENT in requirements:
1046 1081 slow_path = ui.config(
1047 1082 b'storage', b'revlog.persistent-nodemap.slow-path'
1048 1083 )
1049 1084 if slow_path not in (b'allow', b'warn', b'abort'):
1050 1085 default = ui.config_default(
1051 1086 b'storage', b'revlog.persistent-nodemap.slow-path'
1052 1087 )
1053 1088 msg = _(
1054 1089 b'unknown value for config '
1055 1090 b'"storage.revlog.persistent-nodemap.slow-path": "%s"\n'
1056 1091 )
1057 1092 ui.warn(msg % slow_path)
1058 1093 if not ui.quiet:
1059 1094 ui.warn(_(b'falling back to default value: %s\n') % default)
1060 1095 slow_path = default
1061 1096
1062 1097 msg = _(
1063 1098 b"accessing `persistent-nodemap` repository without associated "
1064 1099 b"fast implementation."
1065 1100 )
1066 1101 hint = _(
1067 1102 b"check `hg help config.format.use-persistent-nodemap` "
1068 1103 b"for details"
1069 1104 )
1070 1105 if not revlog.HAS_FAST_PERSISTENT_NODEMAP:
1071 1106 if slow_path == b'warn':
1072 1107 msg = b"warning: " + msg + b'\n'
1073 1108 ui.warn(msg)
1074 1109 if not ui.quiet:
1075 1110 hint = b'(' + hint + b')\n'
1076 1111 ui.warn(hint)
1077 1112 if slow_path == b'abort':
1078 1113 raise error.Abort(msg, hint=hint)
1079 1114 options[b'persistent-nodemap'] = True
1080 1115 if ui.configbool(b'storage', b'revlog.persistent-nodemap.mmap'):
1081 1116 options[b'persistent-nodemap.mmap'] = True
1082 1117 if ui.configbool(b'devel', b'persistent-nodemap'):
1083 1118 options[b'devel-force-nodemap'] = True
1084 1119
1085 1120 return options
1086 1121
1087 1122
1088 1123 def makemain(**kwargs):
1089 1124 """Produce a type conforming to ``ilocalrepositorymain``."""
1090 1125 return localrepository
1091 1126
1092 1127
1093 1128 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1094 1129 class revlogfilestorage(object):
1095 1130 """File storage when using revlogs."""
1096 1131
1097 1132 def file(self, path):
1098 1133 if path[0] == b'/':
1099 1134 path = path[1:]
1100 1135
1101 1136 return filelog.filelog(self.svfs, path)
1102 1137
1103 1138
1104 1139 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
1105 1140 class revlognarrowfilestorage(object):
1106 1141 """File storage when using revlogs and narrow files."""
1107 1142
1108 1143 def file(self, path):
1109 1144 if path[0] == b'/':
1110 1145 path = path[1:]
1111 1146
1112 1147 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
1113 1148
1114 1149
1115 1150 def makefilestorage(requirements, features, **kwargs):
1116 1151 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
1117 1152 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
1118 1153 features.add(repository.REPO_FEATURE_STREAM_CLONE)
1119 1154
1120 1155 if requirementsmod.NARROW_REQUIREMENT in requirements:
1121 1156 return revlognarrowfilestorage
1122 1157 else:
1123 1158 return revlogfilestorage
1124 1159
1125 1160
1126 1161 # List of repository interfaces and factory functions for them. Each
1127 1162 # will be called in order during ``makelocalrepository()`` to iteratively
1128 1163 # derive the final type for a local repository instance. We capture the
1129 1164 # function as a lambda so we don't hold a reference and the module-level
1130 1165 # functions can be wrapped.
1131 1166 REPO_INTERFACES = [
1132 1167 (repository.ilocalrepositorymain, lambda: makemain),
1133 1168 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
1134 1169 ]
1135 1170
1136 1171
1137 1172 @interfaceutil.implementer(repository.ilocalrepositorymain)
1138 1173 class localrepository(object):
1139 1174 """Main class for representing local repositories.
1140 1175
1141 1176 All local repositories are instances of this class.
1142 1177
1143 1178 Constructed on its own, instances of this class are not usable as
1144 1179 repository objects. To obtain a usable repository object, call
1145 1180 ``hg.repository()``, ``localrepo.instance()``, or
1146 1181 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
1147 1182 ``instance()`` adds support for creating new repositories.
1148 1183 ``hg.repository()`` adds more extension integration, including calling
1149 1184 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
1150 1185 used.
1151 1186 """
1152 1187
1153 1188 # obsolete experimental requirements:
1154 1189 # - manifestv2: An experimental new manifest format that allowed
1155 1190 # for stem compression of long paths. Experiment ended up not
1156 1191 # being successful (repository sizes went up due to worse delta
1157 1192 # chains), and the code was deleted in 4.6.
1158 1193 supportedformats = {
1159 1194 b'revlogv1',
1160 1195 b'generaldelta',
1161 1196 requirementsmod.TREEMANIFEST_REQUIREMENT,
1162 1197 requirementsmod.COPIESSDC_REQUIREMENT,
1163 1198 requirementsmod.REVLOGV2_REQUIREMENT,
1164 1199 requirementsmod.SIDEDATA_REQUIREMENT,
1165 1200 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1166 1201 requirementsmod.NODEMAP_REQUIREMENT,
1167 1202 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
1168 1203 requirementsmod.SHARESAFE_REQUIREMENT,
1169 1204 }
1170 1205 _basesupported = supportedformats | {
1171 1206 b'store',
1172 1207 b'fncache',
1173 1208 requirementsmod.SHARED_REQUIREMENT,
1174 1209 requirementsmod.RELATIVE_SHARED_REQUIREMENT,
1175 1210 b'dotencode',
1176 1211 requirementsmod.SPARSE_REQUIREMENT,
1177 1212 requirementsmod.INTERNAL_PHASE_REQUIREMENT,
1178 1213 }
1179 1214
1180 1215 # list of prefix for file which can be written without 'wlock'
1181 1216 # Extensions should extend this list when needed
1182 1217 _wlockfreeprefix = {
1183 1218 # We migh consider requiring 'wlock' for the next
1184 1219 # two, but pretty much all the existing code assume
1185 1220 # wlock is not needed so we keep them excluded for
1186 1221 # now.
1187 1222 b'hgrc',
1188 1223 b'requires',
1189 1224 # XXX cache is a complicatged business someone
1190 1225 # should investigate this in depth at some point
1191 1226 b'cache/',
1192 1227 # XXX shouldn't be dirstate covered by the wlock?
1193 1228 b'dirstate',
1194 1229 # XXX bisect was still a bit too messy at the time
1195 1230 # this changeset was introduced. Someone should fix
1196 1231 # the remainig bit and drop this line
1197 1232 b'bisect.state',
1198 1233 }
1199 1234
1200 1235 def __init__(
1201 1236 self,
1202 1237 baseui,
1203 1238 ui,
1204 1239 origroot,
1205 1240 wdirvfs,
1206 1241 hgvfs,
1207 1242 requirements,
1208 1243 supportedrequirements,
1209 1244 sharedpath,
1210 1245 store,
1211 1246 cachevfs,
1212 1247 wcachevfs,
1213 1248 features,
1214 1249 intents=None,
1215 1250 ):
1216 1251 """Create a new local repository instance.
1217 1252
1218 1253 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
1219 1254 or ``localrepo.makelocalrepository()`` for obtaining a new repository
1220 1255 object.
1221 1256
1222 1257 Arguments:
1223 1258
1224 1259 baseui
1225 1260 ``ui.ui`` instance that ``ui`` argument was based off of.
1226 1261
1227 1262 ui
1228 1263 ``ui.ui`` instance for use by the repository.
1229 1264
1230 1265 origroot
1231 1266 ``bytes`` path to working directory root of this repository.
1232 1267
1233 1268 wdirvfs
1234 1269 ``vfs.vfs`` rooted at the working directory.
1235 1270
1236 1271 hgvfs
1237 1272 ``vfs.vfs`` rooted at .hg/
1238 1273
1239 1274 requirements
1240 1275 ``set`` of bytestrings representing repository opening requirements.
1241 1276
1242 1277 supportedrequirements
1243 1278 ``set`` of bytestrings representing repository requirements that we
1244 1279 know how to open. May be a supetset of ``requirements``.
1245 1280
1246 1281 sharedpath
1247 1282 ``bytes`` Defining path to storage base directory. Points to a
1248 1283 ``.hg/`` directory somewhere.
1249 1284
1250 1285 store
1251 1286 ``store.basicstore`` (or derived) instance providing access to
1252 1287 versioned storage.
1253 1288
1254 1289 cachevfs
1255 1290 ``vfs.vfs`` used for cache files.
1256 1291
1257 1292 wcachevfs
1258 1293 ``vfs.vfs`` used for cache files related to the working copy.
1259 1294
1260 1295 features
1261 1296 ``set`` of bytestrings defining features/capabilities of this
1262 1297 instance.
1263 1298
1264 1299 intents
1265 1300 ``set`` of system strings indicating what this repo will be used
1266 1301 for.
1267 1302 """
1268 1303 self.baseui = baseui
1269 1304 self.ui = ui
1270 1305 self.origroot = origroot
1271 1306 # vfs rooted at working directory.
1272 1307 self.wvfs = wdirvfs
1273 1308 self.root = wdirvfs.base
1274 1309 # vfs rooted at .hg/. Used to access most non-store paths.
1275 1310 self.vfs = hgvfs
1276 1311 self.path = hgvfs.base
1277 1312 self.requirements = requirements
1278 1313 self.supported = supportedrequirements
1279 1314 self.sharedpath = sharedpath
1280 1315 self.store = store
1281 1316 self.cachevfs = cachevfs
1282 1317 self.wcachevfs = wcachevfs
1283 1318 self.features = features
1284 1319
1285 1320 self.filtername = None
1286 1321
1287 1322 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1288 1323 b'devel', b'check-locks'
1289 1324 ):
1290 1325 self.vfs.audit = self._getvfsward(self.vfs.audit)
1291 1326 # A list of callback to shape the phase if no data were found.
1292 1327 # Callback are in the form: func(repo, roots) --> processed root.
1293 1328 # This list it to be filled by extension during repo setup
1294 1329 self._phasedefaults = []
1295 1330
1296 1331 color.setup(self.ui)
1297 1332
1298 1333 self.spath = self.store.path
1299 1334 self.svfs = self.store.vfs
1300 1335 self.sjoin = self.store.join
1301 1336 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
1302 1337 b'devel', b'check-locks'
1303 1338 ):
1304 1339 if util.safehasattr(self.svfs, b'vfs'): # this is filtervfs
1305 1340 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1306 1341 else: # standard vfs
1307 1342 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1308 1343
1309 1344 self._dirstatevalidatewarned = False
1310 1345
1311 1346 self._branchcaches = branchmap.BranchMapCache()
1312 1347 self._revbranchcache = None
1313 1348 self._filterpats = {}
1314 1349 self._datafilters = {}
1315 1350 self._transref = self._lockref = self._wlockref = None
1316 1351
1317 1352 # A cache for various files under .hg/ that tracks file changes,
1318 1353 # (used by the filecache decorator)
1319 1354 #
1320 1355 # Maps a property name to its util.filecacheentry
1321 1356 self._filecache = {}
1322 1357
1323 1358 # hold sets of revision to be filtered
1324 1359 # should be cleared when something might have changed the filter value:
1325 1360 # - new changesets,
1326 1361 # - phase change,
1327 1362 # - new obsolescence marker,
1328 1363 # - working directory parent change,
1329 1364 # - bookmark changes
1330 1365 self.filteredrevcache = {}
1331 1366
1332 1367 # post-dirstate-status hooks
1333 1368 self._postdsstatus = []
1334 1369
1335 1370 # generic mapping between names and nodes
1336 1371 self.names = namespaces.namespaces()
1337 1372
1338 1373 # Key to signature value.
1339 1374 self._sparsesignaturecache = {}
1340 1375 # Signature to cached matcher instance.
1341 1376 self._sparsematchercache = {}
1342 1377
1343 1378 self._extrafilterid = repoview.extrafilter(ui)
1344 1379
1345 1380 self.filecopiesmode = None
1346 1381 if requirementsmod.COPIESSDC_REQUIREMENT in self.requirements:
1347 1382 self.filecopiesmode = b'changeset-sidedata'
1348 1383
1349 1384 def _getvfsward(self, origfunc):
1350 1385 """build a ward for self.vfs"""
1351 1386 rref = weakref.ref(self)
1352 1387
1353 1388 def checkvfs(path, mode=None):
1354 1389 ret = origfunc(path, mode=mode)
1355 1390 repo = rref()
1356 1391 if (
1357 1392 repo is None
1358 1393 or not util.safehasattr(repo, b'_wlockref')
1359 1394 or not util.safehasattr(repo, b'_lockref')
1360 1395 ):
1361 1396 return
1362 1397 if mode in (None, b'r', b'rb'):
1363 1398 return
1364 1399 if path.startswith(repo.path):
1365 1400 # truncate name relative to the repository (.hg)
1366 1401 path = path[len(repo.path) + 1 :]
1367 1402 if path.startswith(b'cache/'):
1368 1403 msg = b'accessing cache with vfs instead of cachevfs: "%s"'
1369 1404 repo.ui.develwarn(msg % path, stacklevel=3, config=b"cache-vfs")
1370 1405 # path prefixes covered by 'lock'
1371 1406 vfs_path_prefixes = (
1372 1407 b'journal.',
1373 1408 b'undo.',
1374 1409 b'strip-backup/',
1375 1410 b'cache/',
1376 1411 )
1377 1412 if any(path.startswith(prefix) for prefix in vfs_path_prefixes):
1378 1413 if repo._currentlock(repo._lockref) is None:
1379 1414 repo.ui.develwarn(
1380 1415 b'write with no lock: "%s"' % path,
1381 1416 stacklevel=3,
1382 1417 config=b'check-locks',
1383 1418 )
1384 1419 elif repo._currentlock(repo._wlockref) is None:
1385 1420 # rest of vfs files are covered by 'wlock'
1386 1421 #
1387 1422 # exclude special files
1388 1423 for prefix in self._wlockfreeprefix:
1389 1424 if path.startswith(prefix):
1390 1425 return
1391 1426 repo.ui.develwarn(
1392 1427 b'write with no wlock: "%s"' % path,
1393 1428 stacklevel=3,
1394 1429 config=b'check-locks',
1395 1430 )
1396 1431 return ret
1397 1432
1398 1433 return checkvfs
1399 1434
1400 1435 def _getsvfsward(self, origfunc):
1401 1436 """build a ward for self.svfs"""
1402 1437 rref = weakref.ref(self)
1403 1438
1404 1439 def checksvfs(path, mode=None):
1405 1440 ret = origfunc(path, mode=mode)
1406 1441 repo = rref()
1407 1442 if repo is None or not util.safehasattr(repo, b'_lockref'):
1408 1443 return
1409 1444 if mode in (None, b'r', b'rb'):
1410 1445 return
1411 1446 if path.startswith(repo.sharedpath):
1412 1447 # truncate name relative to the repository (.hg)
1413 1448 path = path[len(repo.sharedpath) + 1 :]
1414 1449 if repo._currentlock(repo._lockref) is None:
1415 1450 repo.ui.develwarn(
1416 1451 b'write with no lock: "%s"' % path, stacklevel=4
1417 1452 )
1418 1453 return ret
1419 1454
1420 1455 return checksvfs
1421 1456
1422 1457 def close(self):
1423 1458 self._writecaches()
1424 1459
1425 1460 def _writecaches(self):
1426 1461 if self._revbranchcache:
1427 1462 self._revbranchcache.write()
1428 1463
1429 1464 def _restrictcapabilities(self, caps):
1430 1465 if self.ui.configbool(b'experimental', b'bundle2-advertise'):
1431 1466 caps = set(caps)
1432 1467 capsblob = bundle2.encodecaps(
1433 1468 bundle2.getrepocaps(self, role=b'client')
1434 1469 )
1435 1470 caps.add(b'bundle2=' + urlreq.quote(capsblob))
1436 1471 return caps
1437 1472
1438 1473 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1439 1474 # self -> auditor -> self._checknested -> self
1440 1475
1441 1476 @property
1442 1477 def auditor(self):
1443 1478 # This is only used by context.workingctx.match in order to
1444 1479 # detect files in subrepos.
1445 1480 return pathutil.pathauditor(self.root, callback=self._checknested)
1446 1481
1447 1482 @property
1448 1483 def nofsauditor(self):
1449 1484 # This is only used by context.basectx.match in order to detect
1450 1485 # files in subrepos.
1451 1486 return pathutil.pathauditor(
1452 1487 self.root, callback=self._checknested, realfs=False, cached=True
1453 1488 )
1454 1489
1455 1490 def _checknested(self, path):
1456 1491 """Determine if path is a legal nested repository."""
1457 1492 if not path.startswith(self.root):
1458 1493 return False
1459 1494 subpath = path[len(self.root) + 1 :]
1460 1495 normsubpath = util.pconvert(subpath)
1461 1496
1462 1497 # XXX: Checking against the current working copy is wrong in
1463 1498 # the sense that it can reject things like
1464 1499 #
1465 1500 # $ hg cat -r 10 sub/x.txt
1466 1501 #
1467 1502 # if sub/ is no longer a subrepository in the working copy
1468 1503 # parent revision.
1469 1504 #
1470 1505 # However, it can of course also allow things that would have
1471 1506 # been rejected before, such as the above cat command if sub/
1472 1507 # is a subrepository now, but was a normal directory before.
1473 1508 # The old path auditor would have rejected by mistake since it
1474 1509 # panics when it sees sub/.hg/.
1475 1510 #
1476 1511 # All in all, checking against the working copy seems sensible
1477 1512 # since we want to prevent access to nested repositories on
1478 1513 # the filesystem *now*.
1479 1514 ctx = self[None]
1480 1515 parts = util.splitpath(subpath)
1481 1516 while parts:
1482 1517 prefix = b'/'.join(parts)
1483 1518 if prefix in ctx.substate:
1484 1519 if prefix == normsubpath:
1485 1520 return True
1486 1521 else:
1487 1522 sub = ctx.sub(prefix)
1488 1523 return sub.checknested(subpath[len(prefix) + 1 :])
1489 1524 else:
1490 1525 parts.pop()
1491 1526 return False
1492 1527
1493 1528 def peer(self):
1494 1529 return localpeer(self) # not cached to avoid reference cycle
1495 1530
1496 1531 def unfiltered(self):
1497 1532 """Return unfiltered version of the repository
1498 1533
1499 1534 Intended to be overwritten by filtered repo."""
1500 1535 return self
1501 1536
1502 1537 def filtered(self, name, visibilityexceptions=None):
1503 1538 """Return a filtered version of a repository
1504 1539
1505 1540 The `name` parameter is the identifier of the requested view. This
1506 1541 will return a repoview object set "exactly" to the specified view.
1507 1542
1508 1543 This function does not apply recursive filtering to a repository. For
1509 1544 example calling `repo.filtered("served")` will return a repoview using
1510 1545 the "served" view, regardless of the initial view used by `repo`.
1511 1546
1512 1547 In other word, there is always only one level of `repoview` "filtering".
1513 1548 """
1514 1549 if self._extrafilterid is not None and b'%' not in name:
1515 1550 name = name + b'%' + self._extrafilterid
1516 1551
1517 1552 cls = repoview.newtype(self.unfiltered().__class__)
1518 1553 return cls(self, name, visibilityexceptions)
1519 1554
1520 1555 @mixedrepostorecache(
1521 1556 (b'bookmarks', b'plain'),
1522 1557 (b'bookmarks.current', b'plain'),
1523 1558 (b'bookmarks', b''),
1524 1559 (b'00changelog.i', b''),
1525 1560 )
1526 1561 def _bookmarks(self):
1527 1562 # Since the multiple files involved in the transaction cannot be
1528 1563 # written atomically (with current repository format), there is a race
1529 1564 # condition here.
1530 1565 #
1531 1566 # 1) changelog content A is read
1532 1567 # 2) outside transaction update changelog to content B
1533 1568 # 3) outside transaction update bookmark file referring to content B
1534 1569 # 4) bookmarks file content is read and filtered against changelog-A
1535 1570 #
1536 1571 # When this happens, bookmarks against nodes missing from A are dropped.
1537 1572 #
1538 1573 # Having this happening during read is not great, but it become worse
1539 1574 # when this happen during write because the bookmarks to the "unknown"
1540 1575 # nodes will be dropped for good. However, writes happen within locks.
1541 1576 # This locking makes it possible to have a race free consistent read.
1542 1577 # For this purpose data read from disc before locking are
1543 1578 # "invalidated" right after the locks are taken. This invalidations are
1544 1579 # "light", the `filecache` mechanism keep the data in memory and will
1545 1580 # reuse them if the underlying files did not changed. Not parsing the
1546 1581 # same data multiple times helps performances.
1547 1582 #
1548 1583 # Unfortunately in the case describe above, the files tracked by the
1549 1584 # bookmarks file cache might not have changed, but the in-memory
1550 1585 # content is still "wrong" because we used an older changelog content
1551 1586 # to process the on-disk data. So after locking, the changelog would be
1552 1587 # refreshed but `_bookmarks` would be preserved.
1553 1588 # Adding `00changelog.i` to the list of tracked file is not
1554 1589 # enough, because at the time we build the content for `_bookmarks` in
1555 1590 # (4), the changelog file has already diverged from the content used
1556 1591 # for loading `changelog` in (1)
1557 1592 #
1558 1593 # To prevent the issue, we force the changelog to be explicitly
1559 1594 # reloaded while computing `_bookmarks`. The data race can still happen
1560 1595 # without the lock (with a narrower window), but it would no longer go
1561 1596 # undetected during the lock time refresh.
1562 1597 #
1563 1598 # The new schedule is as follow
1564 1599 #
1565 1600 # 1) filecache logic detect that `_bookmarks` needs to be computed
1566 1601 # 2) cachestat for `bookmarks` and `changelog` are captured (for book)
1567 1602 # 3) We force `changelog` filecache to be tested
1568 1603 # 4) cachestat for `changelog` are captured (for changelog)
1569 1604 # 5) `_bookmarks` is computed and cached
1570 1605 #
1571 1606 # The step in (3) ensure we have a changelog at least as recent as the
1572 1607 # cache stat computed in (1). As a result at locking time:
1573 1608 # * if the changelog did not changed since (1) -> we can reuse the data
1574 1609 # * otherwise -> the bookmarks get refreshed.
1575 1610 self._refreshchangelog()
1576 1611 return bookmarks.bmstore(self)
1577 1612
1578 1613 def _refreshchangelog(self):
1579 1614 """make sure the in memory changelog match the on-disk one"""
1580 1615 if 'changelog' in vars(self) and self.currenttransaction() is None:
1581 1616 del self.changelog
1582 1617
1583 1618 @property
1584 1619 def _activebookmark(self):
1585 1620 return self._bookmarks.active
1586 1621
1587 1622 # _phasesets depend on changelog. what we need is to call
1588 1623 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1589 1624 # can't be easily expressed in filecache mechanism.
1590 1625 @storecache(b'phaseroots', b'00changelog.i')
1591 1626 def _phasecache(self):
1592 1627 return phases.phasecache(self, self._phasedefaults)
1593 1628
1594 1629 @storecache(b'obsstore')
1595 1630 def obsstore(self):
1596 1631 return obsolete.makestore(self.ui, self)
1597 1632
1598 1633 @storecache(b'00changelog.i')
1599 1634 def changelog(self):
1600 1635 # load dirstate before changelog to avoid race see issue6303
1601 1636 self.dirstate.prefetch_parents()
1602 1637 return self.store.changelog(txnutil.mayhavepending(self.root))
1603 1638
1604 1639 @storecache(b'00manifest.i')
1605 1640 def manifestlog(self):
1606 1641 return self.store.manifestlog(self, self._storenarrowmatch)
1607 1642
1608 1643 @repofilecache(b'dirstate')
1609 1644 def dirstate(self):
1610 1645 return self._makedirstate()
1611 1646
1612 1647 def _makedirstate(self):
1613 1648 """Extension point for wrapping the dirstate per-repo."""
1614 1649 sparsematchfn = lambda: sparse.matcher(self)
1615 1650
1616 1651 return dirstate.dirstate(
1617 1652 self.vfs, self.ui, self.root, self._dirstatevalidate, sparsematchfn
1618 1653 )
1619 1654
1620 1655 def _dirstatevalidate(self, node):
1621 1656 try:
1622 1657 self.changelog.rev(node)
1623 1658 return node
1624 1659 except error.LookupError:
1625 1660 if not self._dirstatevalidatewarned:
1626 1661 self._dirstatevalidatewarned = True
1627 1662 self.ui.warn(
1628 1663 _(b"warning: ignoring unknown working parent %s!\n")
1629 1664 % short(node)
1630 1665 )
1631 1666 return nullid
1632 1667
1633 1668 @storecache(narrowspec.FILENAME)
1634 1669 def narrowpats(self):
1635 1670 """matcher patterns for this repository's narrowspec
1636 1671
1637 1672 A tuple of (includes, excludes).
1638 1673 """
1639 1674 return narrowspec.load(self)
1640 1675
1641 1676 @storecache(narrowspec.FILENAME)
1642 1677 def _storenarrowmatch(self):
1643 1678 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1644 1679 return matchmod.always()
1645 1680 include, exclude = self.narrowpats
1646 1681 return narrowspec.match(self.root, include=include, exclude=exclude)
1647 1682
1648 1683 @storecache(narrowspec.FILENAME)
1649 1684 def _narrowmatch(self):
1650 1685 if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
1651 1686 return matchmod.always()
1652 1687 narrowspec.checkworkingcopynarrowspec(self)
1653 1688 include, exclude = self.narrowpats
1654 1689 return narrowspec.match(self.root, include=include, exclude=exclude)
1655 1690
1656 1691 def narrowmatch(self, match=None, includeexact=False):
1657 1692 """matcher corresponding the the repo's narrowspec
1658 1693
1659 1694 If `match` is given, then that will be intersected with the narrow
1660 1695 matcher.
1661 1696
1662 1697 If `includeexact` is True, then any exact matches from `match` will
1663 1698 be included even if they're outside the narrowspec.
1664 1699 """
1665 1700 if match:
1666 1701 if includeexact and not self._narrowmatch.always():
1667 1702 # do not exclude explicitly-specified paths so that they can
1668 1703 # be warned later on
1669 1704 em = matchmod.exact(match.files())
1670 1705 nm = matchmod.unionmatcher([self._narrowmatch, em])
1671 1706 return matchmod.intersectmatchers(match, nm)
1672 1707 return matchmod.intersectmatchers(match, self._narrowmatch)
1673 1708 return self._narrowmatch
1674 1709
1675 1710 def setnarrowpats(self, newincludes, newexcludes):
1676 1711 narrowspec.save(self, newincludes, newexcludes)
1677 1712 self.invalidate(clearfilecache=True)
1678 1713
1679 1714 @unfilteredpropertycache
1680 1715 def _quick_access_changeid_null(self):
1681 1716 return {
1682 1717 b'null': (nullrev, nullid),
1683 1718 nullrev: (nullrev, nullid),
1684 1719 nullid: (nullrev, nullid),
1685 1720 }
1686 1721
1687 1722 @unfilteredpropertycache
1688 1723 def _quick_access_changeid_wc(self):
1689 1724 # also fast path access to the working copy parents
1690 1725 # however, only do it for filter that ensure wc is visible.
1691 1726 quick = self._quick_access_changeid_null.copy()
1692 1727 cl = self.unfiltered().changelog
1693 1728 for node in self.dirstate.parents():
1694 1729 if node == nullid:
1695 1730 continue
1696 1731 rev = cl.index.get_rev(node)
1697 1732 if rev is None:
1698 1733 # unknown working copy parent case:
1699 1734 #
1700 1735 # skip the fast path and let higher code deal with it
1701 1736 continue
1702 1737 pair = (rev, node)
1703 1738 quick[rev] = pair
1704 1739 quick[node] = pair
1705 1740 # also add the parents of the parents
1706 1741 for r in cl.parentrevs(rev):
1707 1742 if r == nullrev:
1708 1743 continue
1709 1744 n = cl.node(r)
1710 1745 pair = (r, n)
1711 1746 quick[r] = pair
1712 1747 quick[n] = pair
1713 1748 p1node = self.dirstate.p1()
1714 1749 if p1node != nullid:
1715 1750 quick[b'.'] = quick[p1node]
1716 1751 return quick
1717 1752
1718 1753 @unfilteredmethod
1719 1754 def _quick_access_changeid_invalidate(self):
1720 1755 if '_quick_access_changeid_wc' in vars(self):
1721 1756 del self.__dict__['_quick_access_changeid_wc']
1722 1757
1723 1758 @property
1724 1759 def _quick_access_changeid(self):
1725 1760 """an helper dictionnary for __getitem__ calls
1726 1761
1727 1762 This contains a list of symbol we can recognise right away without
1728 1763 further processing.
1729 1764 """
1730 1765 if self.filtername in repoview.filter_has_wc:
1731 1766 return self._quick_access_changeid_wc
1732 1767 return self._quick_access_changeid_null
1733 1768
1734 1769 def __getitem__(self, changeid):
1735 1770 # dealing with special cases
1736 1771 if changeid is None:
1737 1772 return context.workingctx(self)
1738 1773 if isinstance(changeid, context.basectx):
1739 1774 return changeid
1740 1775
1741 1776 # dealing with multiple revisions
1742 1777 if isinstance(changeid, slice):
1743 1778 # wdirrev isn't contiguous so the slice shouldn't include it
1744 1779 return [
1745 1780 self[i]
1746 1781 for i in pycompat.xrange(*changeid.indices(len(self)))
1747 1782 if i not in self.changelog.filteredrevs
1748 1783 ]
1749 1784
1750 1785 # dealing with some special values
1751 1786 quick_access = self._quick_access_changeid.get(changeid)
1752 1787 if quick_access is not None:
1753 1788 rev, node = quick_access
1754 1789 return context.changectx(self, rev, node, maybe_filtered=False)
1755 1790 if changeid == b'tip':
1756 1791 node = self.changelog.tip()
1757 1792 rev = self.changelog.rev(node)
1758 1793 return context.changectx(self, rev, node)
1759 1794
1760 1795 # dealing with arbitrary values
1761 1796 try:
1762 1797 if isinstance(changeid, int):
1763 1798 node = self.changelog.node(changeid)
1764 1799 rev = changeid
1765 1800 elif changeid == b'.':
1766 1801 # this is a hack to delay/avoid loading obsmarkers
1767 1802 # when we know that '.' won't be hidden
1768 1803 node = self.dirstate.p1()
1769 1804 rev = self.unfiltered().changelog.rev(node)
1770 1805 elif len(changeid) == 20:
1771 1806 try:
1772 1807 node = changeid
1773 1808 rev = self.changelog.rev(changeid)
1774 1809 except error.FilteredLookupError:
1775 1810 changeid = hex(changeid) # for the error message
1776 1811 raise
1777 1812 except LookupError:
1778 1813 # check if it might have come from damaged dirstate
1779 1814 #
1780 1815 # XXX we could avoid the unfiltered if we had a recognizable
1781 1816 # exception for filtered changeset access
1782 1817 if (
1783 1818 self.local()
1784 1819 and changeid in self.unfiltered().dirstate.parents()
1785 1820 ):
1786 1821 msg = _(b"working directory has unknown parent '%s'!")
1787 1822 raise error.Abort(msg % short(changeid))
1788 1823 changeid = hex(changeid) # for the error message
1789 1824 raise
1790 1825
1791 1826 elif len(changeid) == 40:
1792 1827 node = bin(changeid)
1793 1828 rev = self.changelog.rev(node)
1794 1829 else:
1795 1830 raise error.ProgrammingError(
1796 1831 b"unsupported changeid '%s' of type %s"
1797 1832 % (changeid, pycompat.bytestr(type(changeid)))
1798 1833 )
1799 1834
1800 1835 return context.changectx(self, rev, node)
1801 1836
1802 1837 except (error.FilteredIndexError, error.FilteredLookupError):
1803 1838 raise error.FilteredRepoLookupError(
1804 1839 _(b"filtered revision '%s'") % pycompat.bytestr(changeid)
1805 1840 )
1806 1841 except (IndexError, LookupError):
1807 1842 raise error.RepoLookupError(
1808 1843 _(b"unknown revision '%s'") % pycompat.bytestr(changeid)
1809 1844 )
1810 1845 except error.WdirUnsupported:
1811 1846 return context.workingctx(self)
1812 1847
1813 1848 def __contains__(self, changeid):
1814 1849 """True if the given changeid exists"""
1815 1850 try:
1816 1851 self[changeid]
1817 1852 return True
1818 1853 except error.RepoLookupError:
1819 1854 return False
1820 1855
1821 1856 def __nonzero__(self):
1822 1857 return True
1823 1858
1824 1859 __bool__ = __nonzero__
1825 1860
1826 1861 def __len__(self):
1827 1862 # no need to pay the cost of repoview.changelog
1828 1863 unfi = self.unfiltered()
1829 1864 return len(unfi.changelog)
1830 1865
1831 1866 def __iter__(self):
1832 1867 return iter(self.changelog)
1833 1868
1834 1869 def revs(self, expr, *args):
1835 1870 """Find revisions matching a revset.
1836 1871
1837 1872 The revset is specified as a string ``expr`` that may contain
1838 1873 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1839 1874
1840 1875 Revset aliases from the configuration are not expanded. To expand
1841 1876 user aliases, consider calling ``scmutil.revrange()`` or
1842 1877 ``repo.anyrevs([expr], user=True)``.
1843 1878
1844 1879 Returns a smartset.abstractsmartset, which is a list-like interface
1845 1880 that contains integer revisions.
1846 1881 """
1847 1882 tree = revsetlang.spectree(expr, *args)
1848 1883 return revset.makematcher(tree)(self)
1849 1884
1850 1885 def set(self, expr, *args):
1851 1886 """Find revisions matching a revset and emit changectx instances.
1852 1887
1853 1888 This is a convenience wrapper around ``revs()`` that iterates the
1854 1889 result and is a generator of changectx instances.
1855 1890
1856 1891 Revset aliases from the configuration are not expanded. To expand
1857 1892 user aliases, consider calling ``scmutil.revrange()``.
1858 1893 """
1859 1894 for r in self.revs(expr, *args):
1860 1895 yield self[r]
1861 1896
1862 1897 def anyrevs(self, specs, user=False, localalias=None):
1863 1898 """Find revisions matching one of the given revsets.
1864 1899
1865 1900 Revset aliases from the configuration are not expanded by default. To
1866 1901 expand user aliases, specify ``user=True``. To provide some local
1867 1902 definitions overriding user aliases, set ``localalias`` to
1868 1903 ``{name: definitionstring}``.
1869 1904 """
1870 1905 if specs == [b'null']:
1871 1906 return revset.baseset([nullrev])
1872 1907 if specs == [b'.']:
1873 1908 quick_data = self._quick_access_changeid.get(b'.')
1874 1909 if quick_data is not None:
1875 1910 return revset.baseset([quick_data[0]])
1876 1911 if user:
1877 1912 m = revset.matchany(
1878 1913 self.ui,
1879 1914 specs,
1880 1915 lookup=revset.lookupfn(self),
1881 1916 localalias=localalias,
1882 1917 )
1883 1918 else:
1884 1919 m = revset.matchany(None, specs, localalias=localalias)
1885 1920 return m(self)
1886 1921
1887 1922 def url(self):
1888 1923 return b'file:' + self.root
1889 1924
1890 1925 def hook(self, name, throw=False, **args):
1891 1926 """Call a hook, passing this repo instance.
1892 1927
1893 1928 This a convenience method to aid invoking hooks. Extensions likely
1894 1929 won't call this unless they have registered a custom hook or are
1895 1930 replacing code that is expected to call a hook.
1896 1931 """
1897 1932 return hook.hook(self.ui, self, name, throw, **args)
1898 1933
1899 1934 @filteredpropertycache
1900 1935 def _tagscache(self):
1901 1936 """Returns a tagscache object that contains various tags related
1902 1937 caches."""
1903 1938
1904 1939 # This simplifies its cache management by having one decorated
1905 1940 # function (this one) and the rest simply fetch things from it.
1906 1941 class tagscache(object):
1907 1942 def __init__(self):
1908 1943 # These two define the set of tags for this repository. tags
1909 1944 # maps tag name to node; tagtypes maps tag name to 'global' or
1910 1945 # 'local'. (Global tags are defined by .hgtags across all
1911 1946 # heads, and local tags are defined in .hg/localtags.)
1912 1947 # They constitute the in-memory cache of tags.
1913 1948 self.tags = self.tagtypes = None
1914 1949
1915 1950 self.nodetagscache = self.tagslist = None
1916 1951
1917 1952 cache = tagscache()
1918 1953 cache.tags, cache.tagtypes = self._findtags()
1919 1954
1920 1955 return cache
1921 1956
1922 1957 def tags(self):
1923 1958 '''return a mapping of tag to node'''
1924 1959 t = {}
1925 1960 if self.changelog.filteredrevs:
1926 1961 tags, tt = self._findtags()
1927 1962 else:
1928 1963 tags = self._tagscache.tags
1929 1964 rev = self.changelog.rev
1930 1965 for k, v in pycompat.iteritems(tags):
1931 1966 try:
1932 1967 # ignore tags to unknown nodes
1933 1968 rev(v)
1934 1969 t[k] = v
1935 1970 except (error.LookupError, ValueError):
1936 1971 pass
1937 1972 return t
1938 1973
1939 1974 def _findtags(self):
1940 1975 """Do the hard work of finding tags. Return a pair of dicts
1941 1976 (tags, tagtypes) where tags maps tag name to node, and tagtypes
1942 1977 maps tag name to a string like \'global\' or \'local\'.
1943 1978 Subclasses or extensions are free to add their own tags, but
1944 1979 should be aware that the returned dicts will be retained for the
1945 1980 duration of the localrepo object."""
1946 1981
1947 1982 # XXX what tagtype should subclasses/extensions use? Currently
1948 1983 # mq and bookmarks add tags, but do not set the tagtype at all.
1949 1984 # Should each extension invent its own tag type? Should there
1950 1985 # be one tagtype for all such "virtual" tags? Or is the status
1951 1986 # quo fine?
1952 1987
1953 1988 # map tag name to (node, hist)
1954 1989 alltags = tagsmod.findglobaltags(self.ui, self)
1955 1990 # map tag name to tag type
1956 1991 tagtypes = {tag: b'global' for tag in alltags}
1957 1992
1958 1993 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
1959 1994
1960 1995 # Build the return dicts. Have to re-encode tag names because
1961 1996 # the tags module always uses UTF-8 (in order not to lose info
1962 1997 # writing to the cache), but the rest of Mercurial wants them in
1963 1998 # local encoding.
1964 1999 tags = {}
1965 2000 for (name, (node, hist)) in pycompat.iteritems(alltags):
1966 2001 if node != nullid:
1967 2002 tags[encoding.tolocal(name)] = node
1968 2003 tags[b'tip'] = self.changelog.tip()
1969 2004 tagtypes = {
1970 2005 encoding.tolocal(name): value
1971 2006 for (name, value) in pycompat.iteritems(tagtypes)
1972 2007 }
1973 2008 return (tags, tagtypes)
1974 2009
1975 2010 def tagtype(self, tagname):
1976 2011 """
1977 2012 return the type of the given tag. result can be:
1978 2013
1979 2014 'local' : a local tag
1980 2015 'global' : a global tag
1981 2016 None : tag does not exist
1982 2017 """
1983 2018
1984 2019 return self._tagscache.tagtypes.get(tagname)
1985 2020
1986 2021 def tagslist(self):
1987 2022 '''return a list of tags ordered by revision'''
1988 2023 if not self._tagscache.tagslist:
1989 2024 l = []
1990 2025 for t, n in pycompat.iteritems(self.tags()):
1991 2026 l.append((self.changelog.rev(n), t, n))
1992 2027 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
1993 2028
1994 2029 return self._tagscache.tagslist
1995 2030
1996 2031 def nodetags(self, node):
1997 2032 '''return the tags associated with a node'''
1998 2033 if not self._tagscache.nodetagscache:
1999 2034 nodetagscache = {}
2000 2035 for t, n in pycompat.iteritems(self._tagscache.tags):
2001 2036 nodetagscache.setdefault(n, []).append(t)
2002 2037 for tags in pycompat.itervalues(nodetagscache):
2003 2038 tags.sort()
2004 2039 self._tagscache.nodetagscache = nodetagscache
2005 2040 return self._tagscache.nodetagscache.get(node, [])
2006 2041
2007 2042 def nodebookmarks(self, node):
2008 2043 """return the list of bookmarks pointing to the specified node"""
2009 2044 return self._bookmarks.names(node)
2010 2045
2011 2046 def branchmap(self):
2012 2047 """returns a dictionary {branch: [branchheads]} with branchheads
2013 2048 ordered by increasing revision number"""
2014 2049 return self._branchcaches[self]
2015 2050
2016 2051 @unfilteredmethod
2017 2052 def revbranchcache(self):
2018 2053 if not self._revbranchcache:
2019 2054 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
2020 2055 return self._revbranchcache
2021 2056
2022 2057 def branchtip(self, branch, ignoremissing=False):
2023 2058 """return the tip node for a given branch
2024 2059
2025 2060 If ignoremissing is True, then this method will not raise an error.
2026 2061 This is helpful for callers that only expect None for a missing branch
2027 2062 (e.g. namespace).
2028 2063
2029 2064 """
2030 2065 try:
2031 2066 return self.branchmap().branchtip(branch)
2032 2067 except KeyError:
2033 2068 if not ignoremissing:
2034 2069 raise error.RepoLookupError(_(b"unknown branch '%s'") % branch)
2035 2070 else:
2036 2071 pass
2037 2072
2038 2073 def lookup(self, key):
2039 2074 node = scmutil.revsymbol(self, key).node()
2040 2075 if node is None:
2041 2076 raise error.RepoLookupError(_(b"unknown revision '%s'") % key)
2042 2077 return node
2043 2078
2044 2079 def lookupbranch(self, key):
2045 2080 if self.branchmap().hasbranch(key):
2046 2081 return key
2047 2082
2048 2083 return scmutil.revsymbol(self, key).branch()
2049 2084
2050 2085 def known(self, nodes):
2051 2086 cl = self.changelog
2052 2087 get_rev = cl.index.get_rev
2053 2088 filtered = cl.filteredrevs
2054 2089 result = []
2055 2090 for n in nodes:
2056 2091 r = get_rev(n)
2057 2092 resp = not (r is None or r in filtered)
2058 2093 result.append(resp)
2059 2094 return result
2060 2095
2061 2096 def local(self):
2062 2097 return self
2063 2098
2064 2099 def publishing(self):
2065 2100 # it's safe (and desirable) to trust the publish flag unconditionally
2066 2101 # so that we don't finalize changes shared between users via ssh or nfs
2067 2102 return self.ui.configbool(b'phases', b'publish', untrusted=True)
2068 2103
2069 2104 def cancopy(self):
2070 2105 # so statichttprepo's override of local() works
2071 2106 if not self.local():
2072 2107 return False
2073 2108 if not self.publishing():
2074 2109 return True
2075 2110 # if publishing we can't copy if there is filtered content
2076 2111 return not self.filtered(b'visible').changelog.filteredrevs
2077 2112
2078 2113 def shared(self):
2079 2114 '''the type of shared repository (None if not shared)'''
2080 2115 if self.sharedpath != self.path:
2081 2116 return b'store'
2082 2117 return None
2083 2118
2084 2119 def wjoin(self, f, *insidef):
2085 2120 return self.vfs.reljoin(self.root, f, *insidef)
2086 2121
2087 2122 def setparents(self, p1, p2=nullid):
2088 2123 self[None].setparents(p1, p2)
2089 2124 self._quick_access_changeid_invalidate()
2090 2125
2091 2126 def filectx(self, path, changeid=None, fileid=None, changectx=None):
2092 2127 """changeid must be a changeset revision, if specified.
2093 2128 fileid can be a file revision or node."""
2094 2129 return context.filectx(
2095 2130 self, path, changeid, fileid, changectx=changectx
2096 2131 )
2097 2132
2098 2133 def getcwd(self):
2099 2134 return self.dirstate.getcwd()
2100 2135
2101 2136 def pathto(self, f, cwd=None):
2102 2137 return self.dirstate.pathto(f, cwd)
2103 2138
2104 2139 def _loadfilter(self, filter):
2105 2140 if filter not in self._filterpats:
2106 2141 l = []
2107 2142 for pat, cmd in self.ui.configitems(filter):
2108 2143 if cmd == b'!':
2109 2144 continue
2110 2145 mf = matchmod.match(self.root, b'', [pat])
2111 2146 fn = None
2112 2147 params = cmd
2113 2148 for name, filterfn in pycompat.iteritems(self._datafilters):
2114 2149 if cmd.startswith(name):
2115 2150 fn = filterfn
2116 2151 params = cmd[len(name) :].lstrip()
2117 2152 break
2118 2153 if not fn:
2119 2154 fn = lambda s, c, **kwargs: procutil.filter(s, c)
2120 2155 fn.__name__ = 'commandfilter'
2121 2156 # Wrap old filters not supporting keyword arguments
2122 2157 if not pycompat.getargspec(fn)[2]:
2123 2158 oldfn = fn
2124 2159 fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c)
2125 2160 fn.__name__ = 'compat-' + oldfn.__name__
2126 2161 l.append((mf, fn, params))
2127 2162 self._filterpats[filter] = l
2128 2163 return self._filterpats[filter]
2129 2164
2130 2165 def _filter(self, filterpats, filename, data):
2131 2166 for mf, fn, cmd in filterpats:
2132 2167 if mf(filename):
2133 2168 self.ui.debug(
2134 2169 b"filtering %s through %s\n"
2135 2170 % (filename, cmd or pycompat.sysbytes(fn.__name__))
2136 2171 )
2137 2172 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
2138 2173 break
2139 2174
2140 2175 return data
2141 2176
2142 2177 @unfilteredpropertycache
2143 2178 def _encodefilterpats(self):
2144 2179 return self._loadfilter(b'encode')
2145 2180
2146 2181 @unfilteredpropertycache
2147 2182 def _decodefilterpats(self):
2148 2183 return self._loadfilter(b'decode')
2149 2184
2150 2185 def adddatafilter(self, name, filter):
2151 2186 self._datafilters[name] = filter
2152 2187
2153 2188 def wread(self, filename):
2154 2189 if self.wvfs.islink(filename):
2155 2190 data = self.wvfs.readlink(filename)
2156 2191 else:
2157 2192 data = self.wvfs.read(filename)
2158 2193 return self._filter(self._encodefilterpats, filename, data)
2159 2194
2160 2195 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
2161 2196 """write ``data`` into ``filename`` in the working directory
2162 2197
2163 2198 This returns length of written (maybe decoded) data.
2164 2199 """
2165 2200 data = self._filter(self._decodefilterpats, filename, data)
2166 2201 if b'l' in flags:
2167 2202 self.wvfs.symlink(data, filename)
2168 2203 else:
2169 2204 self.wvfs.write(
2170 2205 filename, data, backgroundclose=backgroundclose, **kwargs
2171 2206 )
2172 2207 if b'x' in flags:
2173 2208 self.wvfs.setflags(filename, False, True)
2174 2209 else:
2175 2210 self.wvfs.setflags(filename, False, False)
2176 2211 return len(data)
2177 2212
2178 2213 def wwritedata(self, filename, data):
2179 2214 return self._filter(self._decodefilterpats, filename, data)
2180 2215
2181 2216 def currenttransaction(self):
2182 2217 """return the current transaction or None if non exists"""
2183 2218 if self._transref:
2184 2219 tr = self._transref()
2185 2220 else:
2186 2221 tr = None
2187 2222
2188 2223 if tr and tr.running():
2189 2224 return tr
2190 2225 return None
2191 2226
2192 2227 def transaction(self, desc, report=None):
2193 2228 if self.ui.configbool(b'devel', b'all-warnings') or self.ui.configbool(
2194 2229 b'devel', b'check-locks'
2195 2230 ):
2196 2231 if self._currentlock(self._lockref) is None:
2197 2232 raise error.ProgrammingError(b'transaction requires locking')
2198 2233 tr = self.currenttransaction()
2199 2234 if tr is not None:
2200 2235 return tr.nest(name=desc)
2201 2236
2202 2237 # abort here if the journal already exists
2203 2238 if self.svfs.exists(b"journal"):
2204 2239 raise error.RepoError(
2205 2240 _(b"abandoned transaction found"),
2206 2241 hint=_(b"run 'hg recover' to clean up transaction"),
2207 2242 )
2208 2243
2209 2244 idbase = b"%.40f#%f" % (random.random(), time.time())
2210 2245 ha = hex(hashutil.sha1(idbase).digest())
2211 2246 txnid = b'TXN:' + ha
2212 2247 self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
2213 2248
2214 2249 self._writejournal(desc)
2215 2250 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
2216 2251 if report:
2217 2252 rp = report
2218 2253 else:
2219 2254 rp = self.ui.warn
2220 2255 vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
2221 2256 # we must avoid cyclic reference between repo and transaction.
2222 2257 reporef = weakref.ref(self)
2223 2258 # Code to track tag movement
2224 2259 #
2225 2260 # Since tags are all handled as file content, it is actually quite hard
2226 2261 # to track these movement from a code perspective. So we fallback to a
2227 2262 # tracking at the repository level. One could envision to track changes
2228 2263 # to the '.hgtags' file through changegroup apply but that fails to
2229 2264 # cope with case where transaction expose new heads without changegroup
2230 2265 # being involved (eg: phase movement).
2231 2266 #
2232 2267 # For now, We gate the feature behind a flag since this likely comes
2233 2268 # with performance impacts. The current code run more often than needed
2234 2269 # and do not use caches as much as it could. The current focus is on
2235 2270 # the behavior of the feature so we disable it by default. The flag
2236 2271 # will be removed when we are happy with the performance impact.
2237 2272 #
2238 2273 # Once this feature is no longer experimental move the following
2239 2274 # documentation to the appropriate help section:
2240 2275 #
2241 2276 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
2242 2277 # tags (new or changed or deleted tags). In addition the details of
2243 2278 # these changes are made available in a file at:
2244 2279 # ``REPOROOT/.hg/changes/tags.changes``.
2245 2280 # Make sure you check for HG_TAG_MOVED before reading that file as it
2246 2281 # might exist from a previous transaction even if no tag were touched
2247 2282 # in this one. Changes are recorded in a line base format::
2248 2283 #
2249 2284 # <action> <hex-node> <tag-name>\n
2250 2285 #
2251 2286 # Actions are defined as follow:
2252 2287 # "-R": tag is removed,
2253 2288 # "+A": tag is added,
2254 2289 # "-M": tag is moved (old value),
2255 2290 # "+M": tag is moved (new value),
2256 2291 tracktags = lambda x: None
2257 2292 # experimental config: experimental.hook-track-tags
2258 2293 shouldtracktags = self.ui.configbool(
2259 2294 b'experimental', b'hook-track-tags'
2260 2295 )
2261 2296 if desc != b'strip' and shouldtracktags:
2262 2297 oldheads = self.changelog.headrevs()
2263 2298
2264 2299 def tracktags(tr2):
2265 2300 repo = reporef()
2266 2301 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
2267 2302 newheads = repo.changelog.headrevs()
2268 2303 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
2269 2304 # notes: we compare lists here.
2270 2305 # As we do it only once buiding set would not be cheaper
2271 2306 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
2272 2307 if changes:
2273 2308 tr2.hookargs[b'tag_moved'] = b'1'
2274 2309 with repo.vfs(
2275 2310 b'changes/tags.changes', b'w', atomictemp=True
2276 2311 ) as changesfile:
2277 2312 # note: we do not register the file to the transaction
2278 2313 # because we needs it to still exist on the transaction
2279 2314 # is close (for txnclose hooks)
2280 2315 tagsmod.writediff(changesfile, changes)
2281 2316
2282 2317 def validate(tr2):
2283 2318 """will run pre-closing hooks"""
2284 2319 # XXX the transaction API is a bit lacking here so we take a hacky
2285 2320 # path for now
2286 2321 #
2287 2322 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
2288 2323 # dict is copied before these run. In addition we needs the data
2289 2324 # available to in memory hooks too.
2290 2325 #
2291 2326 # Moreover, we also need to make sure this runs before txnclose
2292 2327 # hooks and there is no "pending" mechanism that would execute
2293 2328 # logic only if hooks are about to run.
2294 2329 #
2295 2330 # Fixing this limitation of the transaction is also needed to track
2296 2331 # other families of changes (bookmarks, phases, obsolescence).
2297 2332 #
2298 2333 # This will have to be fixed before we remove the experimental
2299 2334 # gating.
2300 2335 tracktags(tr2)
2301 2336 repo = reporef()
2302 2337
2303 2338 singleheadopt = (b'experimental', b'single-head-per-branch')
2304 2339 singlehead = repo.ui.configbool(*singleheadopt)
2305 2340 if singlehead:
2306 2341 singleheadsub = repo.ui.configsuboptions(*singleheadopt)[1]
2307 2342 accountclosed = singleheadsub.get(
2308 2343 b"account-closed-heads", False
2309 2344 )
2310 2345 if singleheadsub.get(b"public-changes-only", False):
2311 2346 filtername = b"immutable"
2312 2347 else:
2313 2348 filtername = b"visible"
2314 2349 scmutil.enforcesinglehead(
2315 2350 repo, tr2, desc, accountclosed, filtername
2316 2351 )
2317 2352 if hook.hashook(repo.ui, b'pretxnclose-bookmark'):
2318 2353 for name, (old, new) in sorted(
2319 2354 tr.changes[b'bookmarks'].items()
2320 2355 ):
2321 2356 args = tr.hookargs.copy()
2322 2357 args.update(bookmarks.preparehookargs(name, old, new))
2323 2358 repo.hook(
2324 2359 b'pretxnclose-bookmark',
2325 2360 throw=True,
2326 2361 **pycompat.strkwargs(args)
2327 2362 )
2328 2363 if hook.hashook(repo.ui, b'pretxnclose-phase'):
2329 2364 cl = repo.unfiltered().changelog
2330 2365 for revs, (old, new) in tr.changes[b'phases']:
2331 2366 for rev in revs:
2332 2367 args = tr.hookargs.copy()
2333 2368 node = hex(cl.node(rev))
2334 2369 args.update(phases.preparehookargs(node, old, new))
2335 2370 repo.hook(
2336 2371 b'pretxnclose-phase',
2337 2372 throw=True,
2338 2373 **pycompat.strkwargs(args)
2339 2374 )
2340 2375
2341 2376 repo.hook(
2342 2377 b'pretxnclose', throw=True, **pycompat.strkwargs(tr.hookargs)
2343 2378 )
2344 2379
2345 2380 def releasefn(tr, success):
2346 2381 repo = reporef()
2347 2382 if repo is None:
2348 2383 # If the repo has been GC'd (and this release function is being
2349 2384 # called from transaction.__del__), there's not much we can do,
2350 2385 # so just leave the unfinished transaction there and let the
2351 2386 # user run `hg recover`.
2352 2387 return
2353 2388 if success:
2354 2389 # this should be explicitly invoked here, because
2355 2390 # in-memory changes aren't written out at closing
2356 2391 # transaction, if tr.addfilegenerator (via
2357 2392 # dirstate.write or so) isn't invoked while
2358 2393 # transaction running
2359 2394 repo.dirstate.write(None)
2360 2395 else:
2361 2396 # discard all changes (including ones already written
2362 2397 # out) in this transaction
2363 2398 narrowspec.restorebackup(self, b'journal.narrowspec')
2364 2399 narrowspec.restorewcbackup(self, b'journal.narrowspec.dirstate')
2365 2400 repo.dirstate.restorebackup(None, b'journal.dirstate')
2366 2401
2367 2402 repo.invalidate(clearfilecache=True)
2368 2403
2369 2404 tr = transaction.transaction(
2370 2405 rp,
2371 2406 self.svfs,
2372 2407 vfsmap,
2373 2408 b"journal",
2374 2409 b"undo",
2375 2410 aftertrans(renames),
2376 2411 self.store.createmode,
2377 2412 validator=validate,
2378 2413 releasefn=releasefn,
2379 2414 checkambigfiles=_cachedfiles,
2380 2415 name=desc,
2381 2416 )
2382 2417 tr.changes[b'origrepolen'] = len(self)
2383 2418 tr.changes[b'obsmarkers'] = set()
2384 2419 tr.changes[b'phases'] = []
2385 2420 tr.changes[b'bookmarks'] = {}
2386 2421
2387 2422 tr.hookargs[b'txnid'] = txnid
2388 2423 tr.hookargs[b'txnname'] = desc
2389 2424 tr.hookargs[b'changes'] = tr.changes
2390 2425 # note: writing the fncache only during finalize mean that the file is
2391 2426 # outdated when running hooks. As fncache is used for streaming clone,
2392 2427 # this is not expected to break anything that happen during the hooks.
2393 2428 tr.addfinalize(b'flush-fncache', self.store.write)
2394 2429
2395 2430 def txnclosehook(tr2):
2396 2431 """To be run if transaction is successful, will schedule a hook run"""
2397 2432 # Don't reference tr2 in hook() so we don't hold a reference.
2398 2433 # This reduces memory consumption when there are multiple
2399 2434 # transactions per lock. This can likely go away if issue5045
2400 2435 # fixes the function accumulation.
2401 2436 hookargs = tr2.hookargs
2402 2437
2403 2438 def hookfunc(unused_success):
2404 2439 repo = reporef()
2405 2440 if hook.hashook(repo.ui, b'txnclose-bookmark'):
2406 2441 bmchanges = sorted(tr.changes[b'bookmarks'].items())
2407 2442 for name, (old, new) in bmchanges:
2408 2443 args = tr.hookargs.copy()
2409 2444 args.update(bookmarks.preparehookargs(name, old, new))
2410 2445 repo.hook(
2411 2446 b'txnclose-bookmark',
2412 2447 throw=False,
2413 2448 **pycompat.strkwargs(args)
2414 2449 )
2415 2450
2416 2451 if hook.hashook(repo.ui, b'txnclose-phase'):
2417 2452 cl = repo.unfiltered().changelog
2418 2453 phasemv = sorted(
2419 2454 tr.changes[b'phases'], key=lambda r: r[0][0]
2420 2455 )
2421 2456 for revs, (old, new) in phasemv:
2422 2457 for rev in revs:
2423 2458 args = tr.hookargs.copy()
2424 2459 node = hex(cl.node(rev))
2425 2460 args.update(phases.preparehookargs(node, old, new))
2426 2461 repo.hook(
2427 2462 b'txnclose-phase',
2428 2463 throw=False,
2429 2464 **pycompat.strkwargs(args)
2430 2465 )
2431 2466
2432 2467 repo.hook(
2433 2468 b'txnclose', throw=False, **pycompat.strkwargs(hookargs)
2434 2469 )
2435 2470
2436 2471 reporef()._afterlock(hookfunc)
2437 2472
2438 2473 tr.addfinalize(b'txnclose-hook', txnclosehook)
2439 2474 # Include a leading "-" to make it happen before the transaction summary
2440 2475 # reports registered via scmutil.registersummarycallback() whose names
2441 2476 # are 00-txnreport etc. That way, the caches will be warm when the
2442 2477 # callbacks run.
2443 2478 tr.addpostclose(b'-warm-cache', self._buildcacheupdater(tr))
2444 2479
2445 2480 def txnaborthook(tr2):
2446 2481 """To be run if transaction is aborted"""
2447 2482 reporef().hook(
2448 2483 b'txnabort', throw=False, **pycompat.strkwargs(tr2.hookargs)
2449 2484 )
2450 2485
2451 2486 tr.addabort(b'txnabort-hook', txnaborthook)
2452 2487 # avoid eager cache invalidation. in-memory data should be identical
2453 2488 # to stored data if transaction has no error.
2454 2489 tr.addpostclose(b'refresh-filecachestats', self._refreshfilecachestats)
2455 2490 self._transref = weakref.ref(tr)
2456 2491 scmutil.registersummarycallback(self, tr, desc)
2457 2492 return tr
2458 2493
2459 2494 def _journalfiles(self):
2460 2495 return (
2461 2496 (self.svfs, b'journal'),
2462 2497 (self.svfs, b'journal.narrowspec'),
2463 2498 (self.vfs, b'journal.narrowspec.dirstate'),
2464 2499 (self.vfs, b'journal.dirstate'),
2465 2500 (self.vfs, b'journal.branch'),
2466 2501 (self.vfs, b'journal.desc'),
2467 2502 (bookmarks.bookmarksvfs(self), b'journal.bookmarks'),
2468 2503 (self.svfs, b'journal.phaseroots'),
2469 2504 )
2470 2505
2471 2506 def undofiles(self):
2472 2507 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
2473 2508
2474 2509 @unfilteredmethod
2475 2510 def _writejournal(self, desc):
2476 2511 self.dirstate.savebackup(None, b'journal.dirstate')
2477 2512 narrowspec.savewcbackup(self, b'journal.narrowspec.dirstate')
2478 2513 narrowspec.savebackup(self, b'journal.narrowspec')
2479 2514 self.vfs.write(
2480 2515 b"journal.branch", encoding.fromlocal(self.dirstate.branch())
2481 2516 )
2482 2517 self.vfs.write(b"journal.desc", b"%d\n%s\n" % (len(self), desc))
2483 2518 bookmarksvfs = bookmarks.bookmarksvfs(self)
2484 2519 bookmarksvfs.write(
2485 2520 b"journal.bookmarks", bookmarksvfs.tryread(b"bookmarks")
2486 2521 )
2487 2522 self.svfs.write(b"journal.phaseroots", self.svfs.tryread(b"phaseroots"))
2488 2523
2489 2524 def recover(self):
2490 2525 with self.lock():
2491 2526 if self.svfs.exists(b"journal"):
2492 2527 self.ui.status(_(b"rolling back interrupted transaction\n"))
2493 2528 vfsmap = {
2494 2529 b'': self.svfs,
2495 2530 b'plain': self.vfs,
2496 2531 }
2497 2532 transaction.rollback(
2498 2533 self.svfs,
2499 2534 vfsmap,
2500 2535 b"journal",
2501 2536 self.ui.warn,
2502 2537 checkambigfiles=_cachedfiles,
2503 2538 )
2504 2539 self.invalidate()
2505 2540 return True
2506 2541 else:
2507 2542 self.ui.warn(_(b"no interrupted transaction available\n"))
2508 2543 return False
2509 2544
2510 2545 def rollback(self, dryrun=False, force=False):
2511 2546 wlock = lock = dsguard = None
2512 2547 try:
2513 2548 wlock = self.wlock()
2514 2549 lock = self.lock()
2515 2550 if self.svfs.exists(b"undo"):
2516 2551 dsguard = dirstateguard.dirstateguard(self, b'rollback')
2517 2552
2518 2553 return self._rollback(dryrun, force, dsguard)
2519 2554 else:
2520 2555 self.ui.warn(_(b"no rollback information available\n"))
2521 2556 return 1
2522 2557 finally:
2523 2558 release(dsguard, lock, wlock)
2524 2559
2525 2560 @unfilteredmethod # Until we get smarter cache management
2526 2561 def _rollback(self, dryrun, force, dsguard):
2527 2562 ui = self.ui
2528 2563 try:
2529 2564 args = self.vfs.read(b'undo.desc').splitlines()
2530 2565 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2531 2566 if len(args) >= 3:
2532 2567 detail = args[2]
2533 2568 oldtip = oldlen - 1
2534 2569
2535 2570 if detail and ui.verbose:
2536 2571 msg = _(
2537 2572 b'repository tip rolled back to revision %d'
2538 2573 b' (undo %s: %s)\n'
2539 2574 ) % (oldtip, desc, detail)
2540 2575 else:
2541 2576 msg = _(
2542 2577 b'repository tip rolled back to revision %d (undo %s)\n'
2543 2578 ) % (oldtip, desc)
2544 2579 except IOError:
2545 2580 msg = _(b'rolling back unknown transaction\n')
2546 2581 desc = None
2547 2582
2548 2583 if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
2549 2584 raise error.Abort(
2550 2585 _(
2551 2586 b'rollback of last commit while not checked out '
2552 2587 b'may lose data'
2553 2588 ),
2554 2589 hint=_(b'use -f to force'),
2555 2590 )
2556 2591
2557 2592 ui.status(msg)
2558 2593 if dryrun:
2559 2594 return 0
2560 2595
2561 2596 parents = self.dirstate.parents()
2562 2597 self.destroying()
2563 2598 vfsmap = {b'plain': self.vfs, b'': self.svfs}
2564 2599 transaction.rollback(
2565 2600 self.svfs, vfsmap, b'undo', ui.warn, checkambigfiles=_cachedfiles
2566 2601 )
2567 2602 bookmarksvfs = bookmarks.bookmarksvfs(self)
2568 2603 if bookmarksvfs.exists(b'undo.bookmarks'):
2569 2604 bookmarksvfs.rename(
2570 2605 b'undo.bookmarks', b'bookmarks', checkambig=True
2571 2606 )
2572 2607 if self.svfs.exists(b'undo.phaseroots'):
2573 2608 self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
2574 2609 self.invalidate()
2575 2610
2576 2611 has_node = self.changelog.index.has_node
2577 2612 parentgone = any(not has_node(p) for p in parents)
2578 2613 if parentgone:
2579 2614 # prevent dirstateguard from overwriting already restored one
2580 2615 dsguard.close()
2581 2616
2582 2617 narrowspec.restorebackup(self, b'undo.narrowspec')
2583 2618 narrowspec.restorewcbackup(self, b'undo.narrowspec.dirstate')
2584 2619 self.dirstate.restorebackup(None, b'undo.dirstate')
2585 2620 try:
2586 2621 branch = self.vfs.read(b'undo.branch')
2587 2622 self.dirstate.setbranch(encoding.tolocal(branch))
2588 2623 except IOError:
2589 2624 ui.warn(
2590 2625 _(
2591 2626 b'named branch could not be reset: '
2592 2627 b'current branch is still \'%s\'\n'
2593 2628 )
2594 2629 % self.dirstate.branch()
2595 2630 )
2596 2631
2597 2632 parents = tuple([p.rev() for p in self[None].parents()])
2598 2633 if len(parents) > 1:
2599 2634 ui.status(
2600 2635 _(
2601 2636 b'working directory now based on '
2602 2637 b'revisions %d and %d\n'
2603 2638 )
2604 2639 % parents
2605 2640 )
2606 2641 else:
2607 2642 ui.status(
2608 2643 _(b'working directory now based on revision %d\n') % parents
2609 2644 )
2610 2645 mergestatemod.mergestate.clean(self)
2611 2646
2612 2647 # TODO: if we know which new heads may result from this rollback, pass
2613 2648 # them to destroy(), which will prevent the branchhead cache from being
2614 2649 # invalidated.
2615 2650 self.destroyed()
2616 2651 return 0
2617 2652
2618 2653 def _buildcacheupdater(self, newtransaction):
2619 2654 """called during transaction to build the callback updating cache
2620 2655
2621 2656 Lives on the repository to help extension who might want to augment
2622 2657 this logic. For this purpose, the created transaction is passed to the
2623 2658 method.
2624 2659 """
2625 2660 # we must avoid cyclic reference between repo and transaction.
2626 2661 reporef = weakref.ref(self)
2627 2662
2628 2663 def updater(tr):
2629 2664 repo = reporef()
2630 2665 repo.updatecaches(tr)
2631 2666
2632 2667 return updater
2633 2668
2634 2669 @unfilteredmethod
2635 2670 def updatecaches(self, tr=None, full=False):
2636 2671 """warm appropriate caches
2637 2672
2638 2673 If this function is called after a transaction closed. The transaction
2639 2674 will be available in the 'tr' argument. This can be used to selectively
2640 2675 update caches relevant to the changes in that transaction.
2641 2676
2642 2677 If 'full' is set, make sure all caches the function knows about have
2643 2678 up-to-date data. Even the ones usually loaded more lazily.
2644 2679 """
2645 2680 if tr is not None and tr.hookargs.get(b'source') == b'strip':
2646 2681 # During strip, many caches are invalid but
2647 2682 # later call to `destroyed` will refresh them.
2648 2683 return
2649 2684
2650 2685 if tr is None or tr.changes[b'origrepolen'] < len(self):
2651 2686 # accessing the 'served' branchmap should refresh all the others,
2652 2687 self.ui.debug(b'updating the branch cache\n')
2653 2688 self.filtered(b'served').branchmap()
2654 2689 self.filtered(b'served.hidden').branchmap()
2655 2690
2656 2691 if full:
2657 2692 unfi = self.unfiltered()
2658 2693
2659 2694 self.changelog.update_caches(transaction=tr)
2660 2695 self.manifestlog.update_caches(transaction=tr)
2661 2696
2662 2697 rbc = unfi.revbranchcache()
2663 2698 for r in unfi.changelog:
2664 2699 rbc.branchinfo(r)
2665 2700 rbc.write()
2666 2701
2667 2702 # ensure the working copy parents are in the manifestfulltextcache
2668 2703 for ctx in self[b'.'].parents():
2669 2704 ctx.manifest() # accessing the manifest is enough
2670 2705
2671 2706 # accessing fnode cache warms the cache
2672 2707 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2673 2708 # accessing tags warm the cache
2674 2709 self.tags()
2675 2710 self.filtered(b'served').tags()
2676 2711
2677 2712 # The `full` arg is documented as updating even the lazily-loaded
2678 2713 # caches immediately, so we're forcing a write to cause these caches
2679 2714 # to be warmed up even if they haven't explicitly been requested
2680 2715 # yet (if they've never been used by hg, they won't ever have been
2681 2716 # written, even if they're a subset of another kind of cache that
2682 2717 # *has* been used).
2683 2718 for filt in repoview.filtertable.keys():
2684 2719 filtered = self.filtered(filt)
2685 2720 filtered.branchmap().write(filtered)
2686 2721
2687 2722 def invalidatecaches(self):
2688 2723
2689 2724 if '_tagscache' in vars(self):
2690 2725 # can't use delattr on proxy
2691 2726 del self.__dict__['_tagscache']
2692 2727
2693 2728 self._branchcaches.clear()
2694 2729 self.invalidatevolatilesets()
2695 2730 self._sparsesignaturecache.clear()
2696 2731
2697 2732 def invalidatevolatilesets(self):
2698 2733 self.filteredrevcache.clear()
2699 2734 obsolete.clearobscaches(self)
2700 2735 self._quick_access_changeid_invalidate()
2701 2736
2702 2737 def invalidatedirstate(self):
2703 2738 """Invalidates the dirstate, causing the next call to dirstate
2704 2739 to check if it was modified since the last time it was read,
2705 2740 rereading it if it has.
2706 2741
2707 2742 This is different to dirstate.invalidate() that it doesn't always
2708 2743 rereads the dirstate. Use dirstate.invalidate() if you want to
2709 2744 explicitly read the dirstate again (i.e. restoring it to a previous
2710 2745 known good state)."""
2711 2746 if hasunfilteredcache(self, 'dirstate'):
2712 2747 for k in self.dirstate._filecache:
2713 2748 try:
2714 2749 delattr(self.dirstate, k)
2715 2750 except AttributeError:
2716 2751 pass
2717 2752 delattr(self.unfiltered(), 'dirstate')
2718 2753
2719 2754 def invalidate(self, clearfilecache=False):
2720 2755 """Invalidates both store and non-store parts other than dirstate
2721 2756
2722 2757 If a transaction is running, invalidation of store is omitted,
2723 2758 because discarding in-memory changes might cause inconsistency
2724 2759 (e.g. incomplete fncache causes unintentional failure, but
2725 2760 redundant one doesn't).
2726 2761 """
2727 2762 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2728 2763 for k in list(self._filecache.keys()):
2729 2764 # dirstate is invalidated separately in invalidatedirstate()
2730 2765 if k == b'dirstate':
2731 2766 continue
2732 2767 if (
2733 2768 k == b'changelog'
2734 2769 and self.currenttransaction()
2735 2770 and self.changelog._delayed
2736 2771 ):
2737 2772 # The changelog object may store unwritten revisions. We don't
2738 2773 # want to lose them.
2739 2774 # TODO: Solve the problem instead of working around it.
2740 2775 continue
2741 2776
2742 2777 if clearfilecache:
2743 2778 del self._filecache[k]
2744 2779 try:
2745 2780 delattr(unfiltered, k)
2746 2781 except AttributeError:
2747 2782 pass
2748 2783 self.invalidatecaches()
2749 2784 if not self.currenttransaction():
2750 2785 # TODO: Changing contents of store outside transaction
2751 2786 # causes inconsistency. We should make in-memory store
2752 2787 # changes detectable, and abort if changed.
2753 2788 self.store.invalidatecaches()
2754 2789
2755 2790 def invalidateall(self):
2756 2791 """Fully invalidates both store and non-store parts, causing the
2757 2792 subsequent operation to reread any outside changes."""
2758 2793 # extension should hook this to invalidate its caches
2759 2794 self.invalidate()
2760 2795 self.invalidatedirstate()
2761 2796
2762 2797 @unfilteredmethod
2763 2798 def _refreshfilecachestats(self, tr):
2764 2799 """Reload stats of cached files so that they are flagged as valid"""
2765 2800 for k, ce in self._filecache.items():
2766 2801 k = pycompat.sysstr(k)
2767 2802 if k == 'dirstate' or k not in self.__dict__:
2768 2803 continue
2769 2804 ce.refresh()
2770 2805
2771 2806 def _lock(
2772 2807 self,
2773 2808 vfs,
2774 2809 lockname,
2775 2810 wait,
2776 2811 releasefn,
2777 2812 acquirefn,
2778 2813 desc,
2779 2814 ):
2780 2815 timeout = 0
2781 2816 warntimeout = 0
2782 2817 if wait:
2783 2818 timeout = self.ui.configint(b"ui", b"timeout")
2784 2819 warntimeout = self.ui.configint(b"ui", b"timeout.warn")
2785 2820 # internal config: ui.signal-safe-lock
2786 2821 signalsafe = self.ui.configbool(b'ui', b'signal-safe-lock')
2787 2822
2788 2823 l = lockmod.trylock(
2789 2824 self.ui,
2790 2825 vfs,
2791 2826 lockname,
2792 2827 timeout,
2793 2828 warntimeout,
2794 2829 releasefn=releasefn,
2795 2830 acquirefn=acquirefn,
2796 2831 desc=desc,
2797 2832 signalsafe=signalsafe,
2798 2833 )
2799 2834 return l
2800 2835
2801 2836 def _afterlock(self, callback):
2802 2837 """add a callback to be run when the repository is fully unlocked
2803 2838
2804 2839 The callback will be executed when the outermost lock is released
2805 2840 (with wlock being higher level than 'lock')."""
2806 2841 for ref in (self._wlockref, self._lockref):
2807 2842 l = ref and ref()
2808 2843 if l and l.held:
2809 2844 l.postrelease.append(callback)
2810 2845 break
2811 2846 else: # no lock have been found.
2812 2847 callback(True)
2813 2848
2814 2849 def lock(self, wait=True):
2815 2850 """Lock the repository store (.hg/store) and return a weak reference
2816 2851 to the lock. Use this before modifying the store (e.g. committing or
2817 2852 stripping). If you are opening a transaction, get a lock as well.)
2818 2853
2819 2854 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2820 2855 'wlock' first to avoid a dead-lock hazard."""
2821 2856 l = self._currentlock(self._lockref)
2822 2857 if l is not None:
2823 2858 l.lock()
2824 2859 return l
2825 2860
2826 2861 l = self._lock(
2827 2862 vfs=self.svfs,
2828 2863 lockname=b"lock",
2829 2864 wait=wait,
2830 2865 releasefn=None,
2831 2866 acquirefn=self.invalidate,
2832 2867 desc=_(b'repository %s') % self.origroot,
2833 2868 )
2834 2869 self._lockref = weakref.ref(l)
2835 2870 return l
2836 2871
2837 2872 def wlock(self, wait=True):
2838 2873 """Lock the non-store parts of the repository (everything under
2839 2874 .hg except .hg/store) and return a weak reference to the lock.
2840 2875
2841 2876 Use this before modifying files in .hg.
2842 2877
2843 2878 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2844 2879 'wlock' first to avoid a dead-lock hazard."""
2845 2880 l = self._wlockref and self._wlockref()
2846 2881 if l is not None and l.held:
2847 2882 l.lock()
2848 2883 return l
2849 2884
2850 2885 # We do not need to check for non-waiting lock acquisition. Such
2851 2886 # acquisition would not cause dead-lock as they would just fail.
2852 2887 if wait and (
2853 2888 self.ui.configbool(b'devel', b'all-warnings')
2854 2889 or self.ui.configbool(b'devel', b'check-locks')
2855 2890 ):
2856 2891 if self._currentlock(self._lockref) is not None:
2857 2892 self.ui.develwarn(b'"wlock" acquired after "lock"')
2858 2893
2859 2894 def unlock():
2860 2895 if self.dirstate.pendingparentchange():
2861 2896 self.dirstate.invalidate()
2862 2897 else:
2863 2898 self.dirstate.write(None)
2864 2899
2865 2900 self._filecache[b'dirstate'].refresh()
2866 2901
2867 2902 l = self._lock(
2868 2903 self.vfs,
2869 2904 b"wlock",
2870 2905 wait,
2871 2906 unlock,
2872 2907 self.invalidatedirstate,
2873 2908 _(b'working directory of %s') % self.origroot,
2874 2909 )
2875 2910 self._wlockref = weakref.ref(l)
2876 2911 return l
2877 2912
2878 2913 def _currentlock(self, lockref):
2879 2914 """Returns the lock if it's held, or None if it's not."""
2880 2915 if lockref is None:
2881 2916 return None
2882 2917 l = lockref()
2883 2918 if l is None or not l.held:
2884 2919 return None
2885 2920 return l
2886 2921
2887 2922 def currentwlock(self):
2888 2923 """Returns the wlock if it's held, or None if it's not."""
2889 2924 return self._currentlock(self._wlockref)
2890 2925
2891 2926 def checkcommitpatterns(self, wctx, match, status, fail):
2892 2927 """check for commit arguments that aren't committable"""
2893 2928 if match.isexact() or match.prefix():
2894 2929 matched = set(status.modified + status.added + status.removed)
2895 2930
2896 2931 for f in match.files():
2897 2932 f = self.dirstate.normalize(f)
2898 2933 if f == b'.' or f in matched or f in wctx.substate:
2899 2934 continue
2900 2935 if f in status.deleted:
2901 2936 fail(f, _(b'file not found!'))
2902 2937 # Is it a directory that exists or used to exist?
2903 2938 if self.wvfs.isdir(f) or wctx.p1().hasdir(f):
2904 2939 d = f + b'/'
2905 2940 for mf in matched:
2906 2941 if mf.startswith(d):
2907 2942 break
2908 2943 else:
2909 2944 fail(f, _(b"no match under directory!"))
2910 2945 elif f not in self.dirstate:
2911 2946 fail(f, _(b"file not tracked!"))
2912 2947
2913 2948 @unfilteredmethod
2914 2949 def commit(
2915 2950 self,
2916 2951 text=b"",
2917 2952 user=None,
2918 2953 date=None,
2919 2954 match=None,
2920 2955 force=False,
2921 2956 editor=None,
2922 2957 extra=None,
2923 2958 ):
2924 2959 """Add a new revision to current repository.
2925 2960
2926 2961 Revision information is gathered from the working directory,
2927 2962 match can be used to filter the committed files. If editor is
2928 2963 supplied, it is called to get a commit message.
2929 2964 """
2930 2965 if extra is None:
2931 2966 extra = {}
2932 2967
2933 2968 def fail(f, msg):
2934 2969 raise error.InputError(b'%s: %s' % (f, msg))
2935 2970
2936 2971 if not match:
2937 2972 match = matchmod.always()
2938 2973
2939 2974 if not force:
2940 2975 match.bad = fail
2941 2976
2942 2977 # lock() for recent changelog (see issue4368)
2943 2978 with self.wlock(), self.lock():
2944 2979 wctx = self[None]
2945 2980 merge = len(wctx.parents()) > 1
2946 2981
2947 2982 if not force and merge and not match.always():
2948 2983 raise error.Abort(
2949 2984 _(
2950 2985 b'cannot partially commit a merge '
2951 2986 b'(do not specify files or patterns)'
2952 2987 )
2953 2988 )
2954 2989
2955 2990 status = self.status(match=match, clean=force)
2956 2991 if force:
2957 2992 status.modified.extend(
2958 2993 status.clean
2959 2994 ) # mq may commit clean files
2960 2995
2961 2996 # check subrepos
2962 2997 subs, commitsubs, newstate = subrepoutil.precommit(
2963 2998 self.ui, wctx, status, match, force=force
2964 2999 )
2965 3000
2966 3001 # make sure all explicit patterns are matched
2967 3002 if not force:
2968 3003 self.checkcommitpatterns(wctx, match, status, fail)
2969 3004
2970 3005 cctx = context.workingcommitctx(
2971 3006 self, status, text, user, date, extra
2972 3007 )
2973 3008
2974 3009 ms = mergestatemod.mergestate.read(self)
2975 3010 mergeutil.checkunresolved(ms)
2976 3011
2977 3012 # internal config: ui.allowemptycommit
2978 3013 if cctx.isempty() and not self.ui.configbool(
2979 3014 b'ui', b'allowemptycommit'
2980 3015 ):
2981 3016 self.ui.debug(b'nothing to commit, clearing merge state\n')
2982 3017 ms.reset()
2983 3018 return None
2984 3019
2985 3020 if merge and cctx.deleted():
2986 3021 raise error.Abort(_(b"cannot commit merge with missing files"))
2987 3022
2988 3023 if editor:
2989 3024 cctx._text = editor(self, cctx, subs)
2990 3025 edited = text != cctx._text
2991 3026
2992 3027 # Save commit message in case this transaction gets rolled back
2993 3028 # (e.g. by a pretxncommit hook). Leave the content alone on
2994 3029 # the assumption that the user will use the same editor again.
2995 3030 msgfn = self.savecommitmessage(cctx._text)
2996 3031
2997 3032 # commit subs and write new state
2998 3033 if subs:
2999 3034 uipathfn = scmutil.getuipathfn(self)
3000 3035 for s in sorted(commitsubs):
3001 3036 sub = wctx.sub(s)
3002 3037 self.ui.status(
3003 3038 _(b'committing subrepository %s\n')
3004 3039 % uipathfn(subrepoutil.subrelpath(sub))
3005 3040 )
3006 3041 sr = sub.commit(cctx._text, user, date)
3007 3042 newstate[s] = (newstate[s][0], sr)
3008 3043 subrepoutil.writestate(self, newstate)
3009 3044
3010 3045 p1, p2 = self.dirstate.parents()
3011 3046 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or b'')
3012 3047 try:
3013 3048 self.hook(
3014 3049 b"precommit", throw=True, parent1=hookp1, parent2=hookp2
3015 3050 )
3016 3051 with self.transaction(b'commit'):
3017 3052 ret = self.commitctx(cctx, True)
3018 3053 # update bookmarks, dirstate and mergestate
3019 3054 bookmarks.update(self, [p1, p2], ret)
3020 3055 cctx.markcommitted(ret)
3021 3056 ms.reset()
3022 3057 except: # re-raises
3023 3058 if edited:
3024 3059 self.ui.write(
3025 3060 _(b'note: commit message saved in %s\n') % msgfn
3026 3061 )
3027 3062 self.ui.write(
3028 3063 _(
3029 3064 b"note: use 'hg commit --logfile "
3030 3065 b".hg/last-message.txt --edit' to reuse it\n"
3031 3066 )
3032 3067 )
3033 3068 raise
3034 3069
3035 3070 def commithook(unused_success):
3036 3071 # hack for command that use a temporary commit (eg: histedit)
3037 3072 # temporary commit got stripped before hook release
3038 3073 if self.changelog.hasnode(ret):
3039 3074 self.hook(
3040 3075 b"commit", node=hex(ret), parent1=hookp1, parent2=hookp2
3041 3076 )
3042 3077
3043 3078 self._afterlock(commithook)
3044 3079 return ret
3045 3080
3046 3081 @unfilteredmethod
3047 3082 def commitctx(self, ctx, error=False, origctx=None):
3048 3083 return commit.commitctx(self, ctx, error=error, origctx=origctx)
3049 3084
3050 3085 @unfilteredmethod
3051 3086 def destroying(self):
3052 3087 """Inform the repository that nodes are about to be destroyed.
3053 3088 Intended for use by strip and rollback, so there's a common
3054 3089 place for anything that has to be done before destroying history.
3055 3090
3056 3091 This is mostly useful for saving state that is in memory and waiting
3057 3092 to be flushed when the current lock is released. Because a call to
3058 3093 destroyed is imminent, the repo will be invalidated causing those
3059 3094 changes to stay in memory (waiting for the next unlock), or vanish
3060 3095 completely.
3061 3096 """
3062 3097 # When using the same lock to commit and strip, the phasecache is left
3063 3098 # dirty after committing. Then when we strip, the repo is invalidated,
3064 3099 # causing those changes to disappear.
3065 3100 if '_phasecache' in vars(self):
3066 3101 self._phasecache.write()
3067 3102
3068 3103 @unfilteredmethod
3069 3104 def destroyed(self):
3070 3105 """Inform the repository that nodes have been destroyed.
3071 3106 Intended for use by strip and rollback, so there's a common
3072 3107 place for anything that has to be done after destroying history.
3073 3108 """
3074 3109 # When one tries to:
3075 3110 # 1) destroy nodes thus calling this method (e.g. strip)
3076 3111 # 2) use phasecache somewhere (e.g. commit)
3077 3112 #
3078 3113 # then 2) will fail because the phasecache contains nodes that were
3079 3114 # removed. We can either remove phasecache from the filecache,
3080 3115 # causing it to reload next time it is accessed, or simply filter
3081 3116 # the removed nodes now and write the updated cache.
3082 3117 self._phasecache.filterunknown(self)
3083 3118 self._phasecache.write()
3084 3119
3085 3120 # refresh all repository caches
3086 3121 self.updatecaches()
3087 3122
3088 3123 # Ensure the persistent tag cache is updated. Doing it now
3089 3124 # means that the tag cache only has to worry about destroyed
3090 3125 # heads immediately after a strip/rollback. That in turn
3091 3126 # guarantees that "cachetip == currenttip" (comparing both rev
3092 3127 # and node) always means no nodes have been added or destroyed.
3093 3128
3094 3129 # XXX this is suboptimal when qrefresh'ing: we strip the current
3095 3130 # head, refresh the tag cache, then immediately add a new head.
3096 3131 # But I think doing it this way is necessary for the "instant
3097 3132 # tag cache retrieval" case to work.
3098 3133 self.invalidate()
3099 3134
3100 3135 def status(
3101 3136 self,
3102 3137 node1=b'.',
3103 3138 node2=None,
3104 3139 match=None,
3105 3140 ignored=False,
3106 3141 clean=False,
3107 3142 unknown=False,
3108 3143 listsubrepos=False,
3109 3144 ):
3110 3145 '''a convenience method that calls node1.status(node2)'''
3111 3146 return self[node1].status(
3112 3147 node2, match, ignored, clean, unknown, listsubrepos
3113 3148 )
3114 3149
3115 3150 def addpostdsstatus(self, ps):
3116 3151 """Add a callback to run within the wlock, at the point at which status
3117 3152 fixups happen.
3118 3153
3119 3154 On status completion, callback(wctx, status) will be called with the
3120 3155 wlock held, unless the dirstate has changed from underneath or the wlock
3121 3156 couldn't be grabbed.
3122 3157
3123 3158 Callbacks should not capture and use a cached copy of the dirstate --
3124 3159 it might change in the meanwhile. Instead, they should access the
3125 3160 dirstate via wctx.repo().dirstate.
3126 3161
3127 3162 This list is emptied out after each status run -- extensions should
3128 3163 make sure it adds to this list each time dirstate.status is called.
3129 3164 Extensions should also make sure they don't call this for statuses
3130 3165 that don't involve the dirstate.
3131 3166 """
3132 3167
3133 3168 # The list is located here for uniqueness reasons -- it is actually
3134 3169 # managed by the workingctx, but that isn't unique per-repo.
3135 3170 self._postdsstatus.append(ps)
3136 3171
3137 3172 def postdsstatus(self):
3138 3173 """Used by workingctx to get the list of post-dirstate-status hooks."""
3139 3174 return self._postdsstatus
3140 3175
3141 3176 def clearpostdsstatus(self):
3142 3177 """Used by workingctx to clear post-dirstate-status hooks."""
3143 3178 del self._postdsstatus[:]
3144 3179
3145 3180 def heads(self, start=None):
3146 3181 if start is None:
3147 3182 cl = self.changelog
3148 3183 headrevs = reversed(cl.headrevs())
3149 3184 return [cl.node(rev) for rev in headrevs]
3150 3185
3151 3186 heads = self.changelog.heads(start)
3152 3187 # sort the output in rev descending order
3153 3188 return sorted(heads, key=self.changelog.rev, reverse=True)
3154 3189
3155 3190 def branchheads(self, branch=None, start=None, closed=False):
3156 3191 """return a (possibly filtered) list of heads for the given branch
3157 3192
3158 3193 Heads are returned in topological order, from newest to oldest.
3159 3194 If branch is None, use the dirstate branch.
3160 3195 If start is not None, return only heads reachable from start.
3161 3196 If closed is True, return heads that are marked as closed as well.
3162 3197 """
3163 3198 if branch is None:
3164 3199 branch = self[None].branch()
3165 3200 branches = self.branchmap()
3166 3201 if not branches.hasbranch(branch):
3167 3202 return []
3168 3203 # the cache returns heads ordered lowest to highest
3169 3204 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
3170 3205 if start is not None:
3171 3206 # filter out the heads that cannot be reached from startrev
3172 3207 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
3173 3208 bheads = [h for h in bheads if h in fbheads]
3174 3209 return bheads
3175 3210
3176 3211 def branches(self, nodes):
3177 3212 if not nodes:
3178 3213 nodes = [self.changelog.tip()]
3179 3214 b = []
3180 3215 for n in nodes:
3181 3216 t = n
3182 3217 while True:
3183 3218 p = self.changelog.parents(n)
3184 3219 if p[1] != nullid or p[0] == nullid:
3185 3220 b.append((t, n, p[0], p[1]))
3186 3221 break
3187 3222 n = p[0]
3188 3223 return b
3189 3224
3190 3225 def between(self, pairs):
3191 3226 r = []
3192 3227
3193 3228 for top, bottom in pairs:
3194 3229 n, l, i = top, [], 0
3195 3230 f = 1
3196 3231
3197 3232 while n != bottom and n != nullid:
3198 3233 p = self.changelog.parents(n)[0]
3199 3234 if i == f:
3200 3235 l.append(n)
3201 3236 f = f * 2
3202 3237 n = p
3203 3238 i += 1
3204 3239
3205 3240 r.append(l)
3206 3241
3207 3242 return r
3208 3243
3209 3244 def checkpush(self, pushop):
3210 3245 """Extensions can override this function if additional checks have
3211 3246 to be performed before pushing, or call it if they override push
3212 3247 command.
3213 3248 """
3214 3249
3215 3250 @unfilteredpropertycache
3216 3251 def prepushoutgoinghooks(self):
3217 3252 """Return util.hooks consists of a pushop with repo, remote, outgoing
3218 3253 methods, which are called before pushing changesets.
3219 3254 """
3220 3255 return util.hooks()
3221 3256
3222 3257 def pushkey(self, namespace, key, old, new):
3223 3258 try:
3224 3259 tr = self.currenttransaction()
3225 3260 hookargs = {}
3226 3261 if tr is not None:
3227 3262 hookargs.update(tr.hookargs)
3228 3263 hookargs = pycompat.strkwargs(hookargs)
3229 3264 hookargs['namespace'] = namespace
3230 3265 hookargs['key'] = key
3231 3266 hookargs['old'] = old
3232 3267 hookargs['new'] = new
3233 3268 self.hook(b'prepushkey', throw=True, **hookargs)
3234 3269 except error.HookAbort as exc:
3235 3270 self.ui.write_err(_(b"pushkey-abort: %s\n") % exc)
3236 3271 if exc.hint:
3237 3272 self.ui.write_err(_(b"(%s)\n") % exc.hint)
3238 3273 return False
3239 3274 self.ui.debug(b'pushing key for "%s:%s"\n' % (namespace, key))
3240 3275 ret = pushkey.push(self, namespace, key, old, new)
3241 3276
3242 3277 def runhook(unused_success):
3243 3278 self.hook(
3244 3279 b'pushkey',
3245 3280 namespace=namespace,
3246 3281 key=key,
3247 3282 old=old,
3248 3283 new=new,
3249 3284 ret=ret,
3250 3285 )
3251 3286
3252 3287 self._afterlock(runhook)
3253 3288 return ret
3254 3289
3255 3290 def listkeys(self, namespace):
3256 3291 self.hook(b'prelistkeys', throw=True, namespace=namespace)
3257 3292 self.ui.debug(b'listing keys for "%s"\n' % namespace)
3258 3293 values = pushkey.list(self, namespace)
3259 3294 self.hook(b'listkeys', namespace=namespace, values=values)
3260 3295 return values
3261 3296
3262 3297 def debugwireargs(self, one, two, three=None, four=None, five=None):
3263 3298 '''used to test argument passing over the wire'''
3264 3299 return b"%s %s %s %s %s" % (
3265 3300 one,
3266 3301 two,
3267 3302 pycompat.bytestr(three),
3268 3303 pycompat.bytestr(four),
3269 3304 pycompat.bytestr(five),
3270 3305 )
3271 3306
3272 3307 def savecommitmessage(self, text):
3273 3308 fp = self.vfs(b'last-message.txt', b'wb')
3274 3309 try:
3275 3310 fp.write(text)
3276 3311 finally:
3277 3312 fp.close()
3278 3313 return self.pathto(fp.name[len(self.root) + 1 :])
3279 3314
3280 3315
3281 3316 # used to avoid circular references so destructors work
3282 3317 def aftertrans(files):
3283 3318 renamefiles = [tuple(t) for t in files]
3284 3319
3285 3320 def a():
3286 3321 for vfs, src, dest in renamefiles:
3287 3322 # if src and dest refer to a same file, vfs.rename is a no-op,
3288 3323 # leaving both src and dest on disk. delete dest to make sure
3289 3324 # the rename couldn't be such a no-op.
3290 3325 vfs.tryunlink(dest)
3291 3326 try:
3292 3327 vfs.rename(src, dest)
3293 3328 except OSError: # journal file does not yet exist
3294 3329 pass
3295 3330
3296 3331 return a
3297 3332
3298 3333
3299 3334 def undoname(fn):
3300 3335 base, name = os.path.split(fn)
3301 3336 assert name.startswith(b'journal')
3302 3337 return os.path.join(base, name.replace(b'journal', b'undo', 1))
3303 3338
3304 3339
3305 3340 def instance(ui, path, create, intents=None, createopts=None):
3306 3341 localpath = util.urllocalpath(path)
3307 3342 if create:
3308 3343 createrepository(ui, localpath, createopts=createopts)
3309 3344
3310 3345 return makelocalrepository(ui, localpath, intents=intents)
3311 3346
3312 3347
3313 3348 def islocal(path):
3314 3349 return True
3315 3350
3316 3351
3317 3352 def defaultcreateopts(ui, createopts=None):
3318 3353 """Populate the default creation options for a repository.
3319 3354
3320 3355 A dictionary of explicitly requested creation options can be passed
3321 3356 in. Missing keys will be populated.
3322 3357 """
3323 3358 createopts = dict(createopts or {})
3324 3359
3325 3360 if b'backend' not in createopts:
3326 3361 # experimental config: storage.new-repo-backend
3327 3362 createopts[b'backend'] = ui.config(b'storage', b'new-repo-backend')
3328 3363
3329 3364 return createopts
3330 3365
3331 3366
3332 3367 def newreporequirements(ui, createopts):
3333 3368 """Determine the set of requirements for a new local repository.
3334 3369
3335 3370 Extensions can wrap this function to specify custom requirements for
3336 3371 new repositories.
3337 3372 """
3338 3373 # If the repo is being created from a shared repository, we copy
3339 3374 # its requirements.
3340 3375 if b'sharedrepo' in createopts:
3341 3376 requirements = set(createopts[b'sharedrepo'].requirements)
3342 3377 if createopts.get(b'sharedrelative'):
3343 3378 requirements.add(requirementsmod.RELATIVE_SHARED_REQUIREMENT)
3344 3379 else:
3345 3380 requirements.add(requirementsmod.SHARED_REQUIREMENT)
3346 3381
3347 3382 return requirements
3348 3383
3349 3384 if b'backend' not in createopts:
3350 3385 raise error.ProgrammingError(
3351 3386 b'backend key not present in createopts; '
3352 3387 b'was defaultcreateopts() called?'
3353 3388 )
3354 3389
3355 3390 if createopts[b'backend'] != b'revlogv1':
3356 3391 raise error.Abort(
3357 3392 _(
3358 3393 b'unable to determine repository requirements for '
3359 3394 b'storage backend: %s'
3360 3395 )
3361 3396 % createopts[b'backend']
3362 3397 )
3363 3398
3364 3399 requirements = {b'revlogv1'}
3365 3400 if ui.configbool(b'format', b'usestore'):
3366 3401 requirements.add(b'store')
3367 3402 if ui.configbool(b'format', b'usefncache'):
3368 3403 requirements.add(b'fncache')
3369 3404 if ui.configbool(b'format', b'dotencode'):
3370 3405 requirements.add(b'dotencode')
3371 3406
3372 3407 compengines = ui.configlist(b'format', b'revlog-compression')
3373 3408 for compengine in compengines:
3374 3409 if compengine in util.compengines:
3375 3410 break
3376 3411 else:
3377 3412 raise error.Abort(
3378 3413 _(
3379 3414 b'compression engines %s defined by '
3380 3415 b'format.revlog-compression not available'
3381 3416 )
3382 3417 % b', '.join(b'"%s"' % e for e in compengines),
3383 3418 hint=_(
3384 3419 b'run "hg debuginstall" to list available '
3385 3420 b'compression engines'
3386 3421 ),
3387 3422 )
3388 3423
3389 3424 # zlib is the historical default and doesn't need an explicit requirement.
3390 3425 if compengine == b'zstd':
3391 3426 requirements.add(b'revlog-compression-zstd')
3392 3427 elif compengine != b'zlib':
3393 3428 requirements.add(b'exp-compression-%s' % compengine)
3394 3429
3395 3430 if scmutil.gdinitconfig(ui):
3396 3431 requirements.add(b'generaldelta')
3397 3432 if ui.configbool(b'format', b'sparse-revlog'):
3398 3433 requirements.add(requirementsmod.SPARSEREVLOG_REQUIREMENT)
3399 3434
3400 3435 # experimental config: format.exp-use-side-data
3401 3436 if ui.configbool(b'format', b'exp-use-side-data'):
3402 3437 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3403 3438 # experimental config: format.exp-use-copies-side-data-changeset
3404 3439 if ui.configbool(b'format', b'exp-use-copies-side-data-changeset'):
3405 3440 requirements.add(requirementsmod.SIDEDATA_REQUIREMENT)
3406 3441 requirements.add(requirementsmod.COPIESSDC_REQUIREMENT)
3407 3442 if ui.configbool(b'experimental', b'treemanifest'):
3408 3443 requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
3409 3444
3410 3445 revlogv2 = ui.config(b'experimental', b'revlogv2')
3411 3446 if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
3412 3447 requirements.remove(b'revlogv1')
3413 3448 # generaldelta is implied by revlogv2.
3414 3449 requirements.discard(b'generaldelta')
3415 3450 requirements.add(requirementsmod.REVLOGV2_REQUIREMENT)
3416 3451 # experimental config: format.internal-phase
3417 3452 if ui.configbool(b'format', b'internal-phase'):
3418 3453 requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
3419 3454
3420 3455 if createopts.get(b'narrowfiles'):
3421 3456 requirements.add(requirementsmod.NARROW_REQUIREMENT)
3422 3457
3423 3458 if createopts.get(b'lfs'):
3424 3459 requirements.add(b'lfs')
3425 3460
3426 3461 if ui.configbool(b'format', b'bookmarks-in-store'):
3427 3462 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3428 3463
3429 3464 if ui.configbool(b'format', b'use-persistent-nodemap'):
3430 3465 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3431 3466
3432 3467 # if share-safe is enabled, let's create the new repository with the new
3433 3468 # requirement
3434 3469 if ui.configbool(b'format', b'exp-share-safe'):
3435 3470 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3436 3471
3437 3472 return requirements
3438 3473
3439 3474
3440 3475 def checkrequirementscompat(ui, requirements):
3441 3476 """Checks compatibility of repository requirements enabled and disabled.
3442 3477
3443 3478 Returns a set of requirements which needs to be dropped because dependend
3444 3479 requirements are not enabled. Also warns users about it"""
3445 3480
3446 3481 dropped = set()
3447 3482
3448 3483 if b'store' not in requirements:
3449 3484 if bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT in requirements:
3450 3485 ui.warn(
3451 3486 _(
3452 3487 b'ignoring enabled \'format.bookmarks-in-store\' config '
3453 3488 b'beacuse it is incompatible with disabled '
3454 3489 b'\'format.usestore\' config\n'
3455 3490 )
3456 3491 )
3457 3492 dropped.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3458 3493
3459 3494 if (
3460 3495 requirementsmod.SHARED_REQUIREMENT in requirements
3461 3496 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
3462 3497 ):
3463 3498 raise error.Abort(
3464 3499 _(
3465 3500 b"cannot create shared repository as source was created"
3466 3501 b" with 'format.usestore' config disabled"
3467 3502 )
3468 3503 )
3469 3504
3470 3505 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3471 3506 ui.warn(
3472 3507 _(
3473 3508 b"ignoring enabled 'format.exp-share-safe' config because "
3474 3509 b"it is incompatible with disabled 'format.usestore'"
3475 3510 b" config\n"
3476 3511 )
3477 3512 )
3478 3513 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3479 3514
3480 3515 return dropped
3481 3516
3482 3517
3483 3518 def filterknowncreateopts(ui, createopts):
3484 3519 """Filters a dict of repo creation options against options that are known.
3485 3520
3486 3521 Receives a dict of repo creation options and returns a dict of those
3487 3522 options that we don't know how to handle.
3488 3523
3489 3524 This function is called as part of repository creation. If the
3490 3525 returned dict contains any items, repository creation will not
3491 3526 be allowed, as it means there was a request to create a repository
3492 3527 with options not recognized by loaded code.
3493 3528
3494 3529 Extensions can wrap this function to filter out creation options
3495 3530 they know how to handle.
3496 3531 """
3497 3532 known = {
3498 3533 b'backend',
3499 3534 b'lfs',
3500 3535 b'narrowfiles',
3501 3536 b'sharedrepo',
3502 3537 b'sharedrelative',
3503 3538 b'shareditems',
3504 3539 b'shallowfilestore',
3505 3540 }
3506 3541
3507 3542 return {k: v for k, v in createopts.items() if k not in known}
3508 3543
3509 3544
3510 3545 def createrepository(ui, path, createopts=None):
3511 3546 """Create a new repository in a vfs.
3512 3547
3513 3548 ``path`` path to the new repo's working directory.
3514 3549 ``createopts`` options for the new repository.
3515 3550
3516 3551 The following keys for ``createopts`` are recognized:
3517 3552
3518 3553 backend
3519 3554 The storage backend to use.
3520 3555 lfs
3521 3556 Repository will be created with ``lfs`` requirement. The lfs extension
3522 3557 will automatically be loaded when the repository is accessed.
3523 3558 narrowfiles
3524 3559 Set up repository to support narrow file storage.
3525 3560 sharedrepo
3526 3561 Repository object from which storage should be shared.
3527 3562 sharedrelative
3528 3563 Boolean indicating if the path to the shared repo should be
3529 3564 stored as relative. By default, the pointer to the "parent" repo
3530 3565 is stored as an absolute path.
3531 3566 shareditems
3532 3567 Set of items to share to the new repository (in addition to storage).
3533 3568 shallowfilestore
3534 3569 Indicates that storage for files should be shallow (not all ancestor
3535 3570 revisions are known).
3536 3571 """
3537 3572 createopts = defaultcreateopts(ui, createopts=createopts)
3538 3573
3539 3574 unknownopts = filterknowncreateopts(ui, createopts)
3540 3575
3541 3576 if not isinstance(unknownopts, dict):
3542 3577 raise error.ProgrammingError(
3543 3578 b'filterknowncreateopts() did not return a dict'
3544 3579 )
3545 3580
3546 3581 if unknownopts:
3547 3582 raise error.Abort(
3548 3583 _(
3549 3584 b'unable to create repository because of unknown '
3550 3585 b'creation option: %s'
3551 3586 )
3552 3587 % b', '.join(sorted(unknownopts)),
3553 3588 hint=_(b'is a required extension not loaded?'),
3554 3589 )
3555 3590
3556 3591 requirements = newreporequirements(ui, createopts=createopts)
3557 3592 requirements -= checkrequirementscompat(ui, requirements)
3558 3593
3559 3594 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3560 3595
3561 3596 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3562 3597 if hgvfs.exists():
3563 3598 raise error.RepoError(_(b'repository %s already exists') % path)
3564 3599
3565 3600 if b'sharedrepo' in createopts:
3566 3601 sharedpath = createopts[b'sharedrepo'].sharedpath
3567 3602
3568 3603 if createopts.get(b'sharedrelative'):
3569 3604 try:
3570 3605 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3571 3606 except (IOError, ValueError) as e:
3572 3607 # ValueError is raised on Windows if the drive letters differ
3573 3608 # on each path.
3574 3609 raise error.Abort(
3575 3610 _(b'cannot calculate relative path'),
3576 3611 hint=stringutil.forcebytestr(e),
3577 3612 )
3578 3613
3579 3614 if not wdirvfs.exists():
3580 3615 wdirvfs.makedirs()
3581 3616
3582 3617 hgvfs.makedir(notindexed=True)
3583 3618 if b'sharedrepo' not in createopts:
3584 3619 hgvfs.mkdir(b'cache')
3585 3620 hgvfs.mkdir(b'wcache')
3586 3621
3587 3622 if b'store' in requirements and b'sharedrepo' not in createopts:
3588 3623 hgvfs.mkdir(b'store')
3589 3624
3590 3625 # We create an invalid changelog outside the store so very old
3591 3626 # Mercurial versions (which didn't know about the requirements
3592 3627 # file) encounter an error on reading the changelog. This
3593 3628 # effectively locks out old clients and prevents them from
3594 3629 # mucking with a repo in an unknown format.
3595 3630 #
3596 3631 # The revlog header has version 2, which won't be recognized by
3597 3632 # such old clients.
3598 3633 hgvfs.append(
3599 3634 b'00changelog.i',
3600 3635 b'\0\0\0\2 dummy changelog to prevent using the old repo '
3601 3636 b'layout',
3602 3637 )
3603 3638
3604 3639 # Filter the requirements into working copy and store ones
3605 3640 wcreq, storereq = scmutil.filterrequirements(requirements)
3606 3641 # write working copy ones
3607 3642 scmutil.writerequires(hgvfs, wcreq)
3608 3643 # If there are store requirements and the current repository
3609 3644 # is not a shared one, write stored requirements
3610 3645 # For new shared repository, we don't need to write the store
3611 3646 # requirements as they are already present in store requires
3612 3647 if storereq and b'sharedrepo' not in createopts:
3613 3648 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3614 3649 scmutil.writerequires(storevfs, storereq)
3615 3650
3616 3651 # Write out file telling readers where to find the shared store.
3617 3652 if b'sharedrepo' in createopts:
3618 3653 hgvfs.write(b'sharedpath', sharedpath)
3619 3654
3620 3655 if createopts.get(b'shareditems'):
3621 3656 shared = b'\n'.join(sorted(createopts[b'shareditems'])) + b'\n'
3622 3657 hgvfs.write(b'shared', shared)
3623 3658
3624 3659
3625 3660 def poisonrepository(repo):
3626 3661 """Poison a repository instance so it can no longer be used."""
3627 3662 # Perform any cleanup on the instance.
3628 3663 repo.close()
3629 3664
3630 3665 # Our strategy is to replace the type of the object with one that
3631 3666 # has all attribute lookups result in error.
3632 3667 #
3633 3668 # But we have to allow the close() method because some constructors
3634 3669 # of repos call close() on repo references.
3635 3670 class poisonedrepository(object):
3636 3671 def __getattribute__(self, item):
3637 3672 if item == 'close':
3638 3673 return object.__getattribute__(self, item)
3639 3674
3640 3675 raise error.ProgrammingError(
3641 3676 b'repo instances should not be used after unshare'
3642 3677 )
3643 3678
3644 3679 def close(self):
3645 3680 pass
3646 3681
3647 3682 # We may have a repoview, which intercepts __setattr__. So be sure
3648 3683 # we operate at the lowest level possible.
3649 3684 object.__setattr__(repo, '__class__', poisonedrepository)
@@ -1,330 +1,340 b''
1 1 # upgrade.py - functions for in place upgrade of Mercurial repository
2 2 #
3 3 # Copyright (c) 2016-present, Gregory Szorc
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 from .i18n import _
11 11 from . import (
12 12 error,
13 13 hg,
14 14 localrepo,
15 15 lock as lockmod,
16 16 pycompat,
17 17 requirements as requirementsmod,
18 18 scmutil,
19 19 )
20 20
21 21 from .upgrade_utils import (
22 22 actions as upgrade_actions,
23 23 engine as upgrade_engine,
24 24 )
25 25
26 26 from .utils import (
27 27 stringutil,
28 28 )
29 29
30 30 allformatvariant = upgrade_actions.allformatvariant
31 31
32 32
33 33 def upgraderepo(
34 34 ui,
35 35 repo,
36 36 run=False,
37 37 optimize=None,
38 38 backup=True,
39 39 manifest=None,
40 40 changelog=None,
41 41 filelogs=None,
42 42 ):
43 43 """Upgrade a repository in place."""
44 44 if optimize is None:
45 45 optimize = {}
46 46 repo = repo.unfiltered()
47 47
48 48 revlogs = set(upgrade_engine.UPGRADE_ALL_REVLOGS)
49 49 specentries = (
50 50 (upgrade_engine.UPGRADE_CHANGELOG, changelog),
51 51 (upgrade_engine.UPGRADE_MANIFEST, manifest),
52 52 (upgrade_engine.UPGRADE_FILELOGS, filelogs),
53 53 )
54 54 specified = [(y, x) for (y, x) in specentries if x is not None]
55 55 if specified:
56 56 # we have some limitation on revlogs to be recloned
57 57 if any(x for y, x in specified):
58 58 revlogs = set()
59 59 for upgrade, enabled in specified:
60 60 if enabled:
61 61 revlogs.add(upgrade)
62 62 else:
63 63 # none are enabled
64 64 for upgrade, __ in specified:
65 65 revlogs.discard(upgrade)
66 66
67 67 # Ensure the repository can be upgraded.
68 68 upgrade_actions.check_source_requirements(repo)
69 69
70 70 default_options = localrepo.defaultcreateopts(repo.ui)
71 71 newreqs = localrepo.newreporequirements(repo.ui, default_options)
72 72 newreqs.update(upgrade_actions.preservedrequirements(repo))
73 73
74 74 upgrade_actions.check_requirements_changes(repo, newreqs)
75 75
76 76 # Find and validate all improvements that can be made.
77 77 alloptimizations = upgrade_actions.findoptimizations(repo)
78 78
79 79 # Apply and Validate arguments.
80 80 optimizations = []
81 81 for o in alloptimizations:
82 82 if o.name in optimize:
83 83 optimizations.append(o)
84 84 optimize.discard(o.name)
85 85
86 86 if optimize: # anything left is unknown
87 87 raise error.Abort(
88 88 _(b'unknown optimization action requested: %s')
89 89 % b', '.join(sorted(optimize)),
90 90 hint=_(b'run without arguments to see valid optimizations'),
91 91 )
92 92
93 93 format_upgrades = upgrade_actions.find_format_upgrades(repo)
94 94 up_actions = upgrade_actions.determine_upgrade_actions(
95 95 repo, format_upgrades, optimizations, repo.requirements, newreqs
96 96 )
97 97 removed_actions = upgrade_actions.find_format_downgrades(repo)
98 98
99 99 removedreqs = repo.requirements - newreqs
100 100 addedreqs = newreqs - repo.requirements
101 101
102 102 if revlogs != upgrade_engine.UPGRADE_ALL_REVLOGS:
103 103 incompatible = upgrade_actions.RECLONES_REQUIREMENTS & (
104 104 removedreqs | addedreqs
105 105 )
106 106 if incompatible:
107 107 msg = _(
108 108 b'ignoring revlogs selection flags, format requirements '
109 109 b'change: %s\n'
110 110 )
111 111 ui.warn(msg % b', '.join(sorted(incompatible)))
112 112 revlogs = upgrade_engine.UPGRADE_ALL_REVLOGS
113 113
114 114 upgrade_op = upgrade_actions.UpgradeOperation(
115 115 ui,
116 116 newreqs,
117 117 repo.requirements,
118 118 up_actions,
119 119 removed_actions,
120 120 revlogs,
121 121 )
122 122
123 123 if not run:
124 124 fromconfig = []
125 125 onlydefault = []
126 126
127 127 for d in format_upgrades:
128 128 if d.fromconfig(repo):
129 129 fromconfig.append(d)
130 130 elif d.default:
131 131 onlydefault.append(d)
132 132
133 133 if fromconfig or onlydefault:
134 134
135 135 if fromconfig:
136 136 ui.status(
137 137 _(
138 138 b'repository lacks features recommended by '
139 139 b'current config options:\n\n'
140 140 )
141 141 )
142 142 for i in fromconfig:
143 143 ui.status(b'%s\n %s\n\n' % (i.name, i.description))
144 144
145 145 if onlydefault:
146 146 ui.status(
147 147 _(
148 148 b'repository lacks features used by the default '
149 149 b'config options:\n\n'
150 150 )
151 151 )
152 152 for i in onlydefault:
153 153 ui.status(b'%s\n %s\n\n' % (i.name, i.description))
154 154
155 155 ui.status(b'\n')
156 156 else:
157 157 ui.status(_(b'(no format upgrades found in existing repository)\n'))
158 158
159 159 ui.status(
160 160 _(
161 161 b'performing an upgrade with "--run" will make the following '
162 162 b'changes:\n\n'
163 163 )
164 164 )
165 165
166 166 upgrade_op.print_requirements()
167 167 upgrade_op.print_optimisations()
168 168 upgrade_op.print_upgrade_actions()
169 169 upgrade_op.print_affected_revlogs()
170 170
171 171 if upgrade_op.unused_optimizations:
172 172 ui.status(
173 173 _(
174 174 b'additional optimizations are available by specifying '
175 175 b'"--optimize <name>":\n\n'
176 176 )
177 177 )
178 178 upgrade_op.print_unused_optimizations()
179 179 return
180 180
181 181 if not (upgrade_op.upgrade_actions or upgrade_op.removed_actions):
182 182 ui.status(_(b'nothing to do\n'))
183 183 return
184 184 # Else we're in the run=true case.
185 185 ui.write(_(b'upgrade will perform the following actions:\n\n'))
186 186 upgrade_op.print_requirements()
187 187 upgrade_op.print_optimisations()
188 188 upgrade_op.print_upgrade_actions()
189 189 upgrade_op.print_affected_revlogs()
190 190
191 191 ui.status(_(b'beginning upgrade...\n'))
192 192 with repo.wlock(), repo.lock():
193 193 ui.status(_(b'repository locked and read-only\n'))
194 194 # Our strategy for upgrading the repository is to create a new,
195 195 # temporary repository, write data to it, then do a swap of the
196 196 # data. There are less heavyweight ways to do this, but it is easier
197 197 # to create a new repo object than to instantiate all the components
198 198 # (like the store) separately.
199 199 tmppath = pycompat.mkdtemp(prefix=b'upgrade.', dir=repo.path)
200 200 backuppath = None
201 201 try:
202 202 ui.status(
203 203 _(
204 204 b'creating temporary repository to stage upgraded '
205 205 b'data: %s\n'
206 206 )
207 207 % tmppath
208 208 )
209 209
210 210 # clone ui without using ui.copy because repo.ui is protected
211 211 repoui = repo.ui.__class__(repo.ui)
212 212 dstrepo = hg.repository(repoui, path=tmppath, create=True)
213 213
214 214 with dstrepo.wlock(), dstrepo.lock():
215 215 backuppath = upgrade_engine.upgrade(
216 216 ui, repo, dstrepo, upgrade_op
217 217 )
218 218 if not backup:
219 219 ui.status(
220 220 _(b'removing old repository content %s\n') % backuppath
221 221 )
222 222 repo.vfs.rmtree(backuppath, forcibly=True)
223 223 backuppath = None
224 224
225 225 finally:
226 226 ui.status(_(b'removing temporary repository %s\n') % tmppath)
227 227 repo.vfs.rmtree(tmppath, forcibly=True)
228 228
229 229 if backuppath and not ui.quiet:
230 230 ui.warn(
231 231 _(b'copy of old repository backed up at %s\n') % backuppath
232 232 )
233 233 ui.warn(
234 234 _(
235 235 b'the old repository will not be deleted; remove '
236 236 b'it to free up disk space once the upgraded '
237 237 b'repository is verified\n'
238 238 )
239 239 )
240 240
241 241 upgrade_op.print_post_op_messages()
242 242
243 243
244 def upgrade_share_to_safe(ui, hgvfs, storevfs, current_requirements):
244 def upgrade_share_to_safe(
245 ui, hgvfs, storevfs, current_requirements, mismatch_config
246 ):
245 247 """Upgrades a share to use share-safe mechanism"""
246 248 wlock = None
247 249 store_requirements = localrepo._readrequires(storevfs, False)
248 250 original_crequirements = current_requirements.copy()
249 251 # after upgrade, store requires will be shared, so lets find
250 252 # the requirements which are not present in store and
251 253 # write them to share's .hg/requires
252 254 diffrequires = current_requirements - store_requirements
253 255 # add share-safe requirement as it will mark the share as share-safe
254 256 diffrequires.add(requirementsmod.SHARESAFE_REQUIREMENT)
255 257 current_requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
258 # in `allow` case, we don't try to upgrade, we just respect the source
259 # state, update requirements and continue
260 if mismatch_config == b'allow':
261 return
256 262 try:
257 263 wlock = lockmod.trylock(ui, hgvfs, b'wlock', 0, 0)
258 264 # some process might change the requirement in between, re-read
259 265 # and update current_requirements
260 266 locked_requirements = localrepo._readrequires(hgvfs, True)
261 267 if locked_requirements != original_crequirements:
262 268 removed = current_requirements - locked_requirements
263 269 # update current_requirements in place because it's passed
264 270 # as reference
265 271 current_requirements -= removed
266 272 current_requirements |= locked_requirements
267 273 diffrequires = current_requirements - store_requirements
268 274 # add share-safe requirement as it will mark the share as share-safe
269 275 diffrequires.add(requirementsmod.SHARESAFE_REQUIREMENT)
270 276 current_requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
271 277 scmutil.writerequires(hgvfs, diffrequires)
272 278 ui.warn(_(b'repository upgraded to use share-safe mode\n'))
273 279 except error.LockError as e:
274 if ui.configbool(b'experimental', b'sharesafe-auto-upgrade-fail-error'):
280 if mismatch_config == b'upgrade-abort':
275 281 raise error.Abort(
276 282 _(b'failed to upgrade share, got error: %s')
277 283 % stringutil.forcebytestr(e.strerror)
278 284 )
279 285 elif ui.configbool(b'experimental', b'sharesafe-warn-outdated-shares'):
280 286 ui.warn(
281 287 _(b'failed to upgrade share, got error: %s\n')
282 288 % stringutil.forcebytestr(e.strerror)
283 289 )
284 290 finally:
285 291 if wlock:
286 292 wlock.release()
287 293
288 294
289 295 def downgrade_share_to_non_safe(
290 296 ui,
291 297 hgvfs,
292 298 sharedvfs,
293 299 current_requirements,
300 mismatch_config,
294 301 ):
295 302 """Downgrades a share which use share-safe to not use it"""
296 303 wlock = None
297 304 source_requirements = localrepo._readrequires(sharedvfs, True)
298 305 original_crequirements = current_requirements.copy()
299 306 # we cannot be 100% sure on which requirements were present in store when
300 307 # the source supported share-safe. However, we do know that working
301 308 # directory requirements were not there. Hence we remove them
302 309 source_requirements -= requirementsmod.WORKING_DIR_REQUIREMENTS
303 310 current_requirements |= source_requirements
304 311 current_requirements.remove(requirementsmod.SHARESAFE_REQUIREMENT)
312 if mismatch_config == b'allow':
313 return
305 314
306 315 try:
307 316 wlock = lockmod.trylock(ui, hgvfs, b'wlock', 0, 0)
308 317 # some process might change the requirement in between, re-read
309 318 # and update current_requirements
310 319 locked_requirements = localrepo._readrequires(hgvfs, True)
311 320 if locked_requirements != original_crequirements:
312 321 removed = current_requirements - locked_requirements
313 322 # update current_requirements in place because it's passed
314 323 # as reference
315 324 current_requirements -= removed
316 325 current_requirements |= locked_requirements
317 326 current_requirements |= source_requirements
318 327 current_requirements -= set(requirementsmod.SHARESAFE_REQUIREMENT)
319 328 scmutil.writerequires(hgvfs, current_requirements)
320 329 ui.warn(_(b'repository downgraded to not use share-safe mode\n'))
321 330 except error.LockError as e:
322 # raise error right away because if downgrade failed, we cannot load
323 # the repository because it does not have complete set of requirements
324 raise error.Abort(
325 _(b'failed to downgrade share, got error: %s')
326 % stringutil.forcebytestr(e.strerror)
327 )
331 # If upgrade-abort is set, abort when upgrade fails, else let the
332 # process continue as `upgrade-allow` is set
333 if mismatch_config == b'downgrade-abort':
334 raise error.Abort(
335 _(b'failed to downgrade share, got error: %s')
336 % stringutil.forcebytestr(e.strerror)
337 )
328 338 finally:
329 339 if wlock:
330 340 wlock.release()
@@ -1,569 +1,574 b''
1 1 setup
2 2
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > share =
6 6 > [format]
7 7 > exp-share-safe = True
8 8 > [storage]
9 9 > revlog.persistent-nodemap.slow-path=allow
10 10 > EOF
11 11
12 12 prepare source repo
13 13
14 14 $ hg init source
15 15 $ cd source
16 16 $ cat .hg/requires
17 17 exp-sharesafe
18 18 $ cat .hg/store/requires
19 19 dotencode
20 20 fncache
21 21 generaldelta
22 22 revlogv1
23 23 sparserevlog
24 24 store
25 25 $ hg debugrequirements
26 26 dotencode
27 27 exp-sharesafe
28 28 fncache
29 29 generaldelta
30 30 revlogv1
31 31 sparserevlog
32 32 store
33 33
34 34 $ echo a > a
35 35 $ hg ci -Aqm "added a"
36 36 $ echo b > b
37 37 $ hg ci -Aqm "added b"
38 38
39 39 $ HGEDITOR=cat hg config --shared
40 40 abort: repository is not shared; can't use --shared
41 41 [10]
42 42 $ cd ..
43 43
44 44 Create a shared repo and check the requirements are shared and read correctly
45 45 $ hg share source shared1
46 46 updating working directory
47 47 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ cd shared1
49 49 $ cat .hg/requires
50 50 exp-sharesafe
51 51 shared
52 52
53 53 $ hg debugrequirements -R ../source
54 54 dotencode
55 55 exp-sharesafe
56 56 fncache
57 57 generaldelta
58 58 revlogv1
59 59 sparserevlog
60 60 store
61 61
62 62 $ hg debugrequirements
63 63 dotencode
64 64 exp-sharesafe
65 65 fncache
66 66 generaldelta
67 67 revlogv1
68 68 shared
69 69 sparserevlog
70 70 store
71 71
72 72 $ echo c > c
73 73 $ hg ci -Aqm "added c"
74 74
75 75 Check that config of the source repository is also loaded
76 76
77 77 $ hg showconfig ui.curses
78 78 [1]
79 79
80 80 $ echo "[ui]" >> ../source/.hg/hgrc
81 81 $ echo "curses=true" >> ../source/.hg/hgrc
82 82
83 83 $ hg showconfig ui.curses
84 84 true
85 85
86 86 Test that extensions of source repository are also loaded
87 87
88 88 $ hg debugextensions
89 89 share
90 90 $ hg extdiff -p echo
91 91 hg: unknown command 'extdiff'
92 92 'extdiff' is provided by the following extension:
93 93
94 94 extdiff command to allow external programs to compare revisions
95 95
96 96 (use 'hg help extensions' for information on enabling extensions)
97 97 [10]
98 98
99 99 $ echo "[extensions]" >> ../source/.hg/hgrc
100 100 $ echo "extdiff=" >> ../source/.hg/hgrc
101 101
102 102 $ hg debugextensions -R ../source
103 103 extdiff
104 104 share
105 105 $ hg extdiff -R ../source -p echo
106 106
107 107 BROKEN: the command below will not work if config of shared source is not loaded
108 108 on dispatch but debugextensions says that extension
109 109 is loaded
110 110 $ hg debugextensions
111 111 extdiff
112 112 share
113 113
114 114 $ hg extdiff -p echo
115 115
116 116 However, local .hg/hgrc should override the config set by share source
117 117
118 118 $ echo "[ui]" >> .hg/hgrc
119 119 $ echo "curses=false" >> .hg/hgrc
120 120
121 121 $ hg showconfig ui.curses
122 122 false
123 123
124 124 $ HGEDITOR=cat hg config --shared
125 125 [ui]
126 126 curses=true
127 127 [extensions]
128 128 extdiff=
129 129
130 130 $ HGEDITOR=cat hg config --local
131 131 [ui]
132 132 curses=false
133 133
134 134 Testing that hooks set in source repository also runs in shared repo
135 135
136 136 $ cd ../source
137 137 $ cat <<EOF >> .hg/hgrc
138 138 > [extensions]
139 139 > hooklib=
140 140 > [hooks]
141 141 > pretxnchangegroup.reject_merge_commits = \
142 142 > python:hgext.hooklib.reject_merge_commits.hook
143 143 > EOF
144 144
145 145 $ cd ..
146 146 $ hg clone source cloned
147 147 updating to branch default
148 148 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 149 $ cd cloned
150 150 $ hg up 0
151 151 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
152 152 $ echo bar > bar
153 153 $ hg ci -Aqm "added bar"
154 154 $ hg merge
155 155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 156 (branch merge, don't forget to commit)
157 157 $ hg ci -m "merge commit"
158 158
159 159 $ hg push ../source
160 160 pushing to ../source
161 161 searching for changes
162 162 adding changesets
163 163 adding manifests
164 164 adding file changes
165 165 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
166 166 transaction abort!
167 167 rollback completed
168 168 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
169 169 [255]
170 170
171 171 $ hg push ../shared1
172 172 pushing to ../shared1
173 173 searching for changes
174 174 adding changesets
175 175 adding manifests
176 176 adding file changes
177 177 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
178 178 transaction abort!
179 179 rollback completed
180 180 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
181 181 [255]
182 182
183 183 Test that if share source config is untrusted, we dont read it
184 184
185 185 $ cd ../shared1
186 186
187 187 $ cat << EOF > $TESTTMP/untrusted.py
188 188 > from mercurial import scmutil, util
189 189 > def uisetup(ui):
190 190 > class untrustedui(ui.__class__):
191 191 > def _trusted(self, fp, f):
192 192 > if util.normpath(fp.name).endswith(b'source/.hg/hgrc'):
193 193 > return False
194 194 > return super(untrustedui, self)._trusted(fp, f)
195 195 > ui.__class__ = untrustedui
196 196 > EOF
197 197
198 198 $ hg showconfig hooks
199 199 hooks.pretxnchangegroup.reject_merge_commits=python:hgext.hooklib.reject_merge_commits.hook
200 200
201 201 $ hg showconfig hooks --config extensions.untrusted=$TESTTMP/untrusted.py
202 202 [1]
203 203
204 204 Update the source repository format and check that shared repo works
205 205
206 206 $ cd ../source
207 207
208 208 Disable zstd related tests because its not present on pure version
209 209 #if zstd
210 210 $ echo "[format]" >> .hg/hgrc
211 211 $ echo "revlog-compression=zstd" >> .hg/hgrc
212 212
213 213 $ hg debugupgraderepo --run -q
214 214 upgrade will perform the following actions:
215 215
216 216 requirements
217 217 preserved: dotencode, exp-sharesafe, fncache, generaldelta, revlogv1, sparserevlog, store
218 218 added: revlog-compression-zstd
219 219
220 220 processed revlogs:
221 221 - all-filelogs
222 222 - changelog
223 223 - manifest
224 224
225 225 $ hg log -r .
226 226 changeset: 1:5f6d8a4bf34a
227 227 user: test
228 228 date: Thu Jan 01 00:00:00 1970 +0000
229 229 summary: added b
230 230
231 231 #endif
232 232 $ echo "[format]" >> .hg/hgrc
233 233 $ echo "use-persistent-nodemap=True" >> .hg/hgrc
234 234
235 235 $ hg debugupgraderepo --run -q -R ../shared1
236 236 abort: cannot upgrade repository; unsupported source requirement: shared
237 237 [255]
238 238
239 239 $ hg debugupgraderepo --run -q
240 240 upgrade will perform the following actions:
241 241
242 242 requirements
243 243 preserved: dotencode, exp-sharesafe, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd !)
244 244 preserved: dotencode, exp-sharesafe, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
245 245 added: persistent-nodemap
246 246
247 247 processed revlogs:
248 248 - all-filelogs
249 249 - changelog
250 250 - manifest
251 251
252 252 $ hg log -r .
253 253 changeset: 1:5f6d8a4bf34a
254 254 user: test
255 255 date: Thu Jan 01 00:00:00 1970 +0000
256 256 summary: added b
257 257
258 258
259 259 Shared one should work
260 260 $ cd ../shared1
261 261 $ hg log -r .
262 262 changeset: 2:155349b645be
263 263 tag: tip
264 264 user: test
265 265 date: Thu Jan 01 00:00:00 1970 +0000
266 266 summary: added c
267 267
268 268
269 269 Testing that nonsharedrc is loaded for source and not shared
270 270
271 271 $ cd ../source
272 272 $ touch .hg/hgrc-not-shared
273 273 $ echo "[ui]" >> .hg/hgrc-not-shared
274 274 $ echo "traceback=true" >> .hg/hgrc-not-shared
275 275
276 276 $ hg showconfig ui.traceback
277 277 true
278 278
279 279 $ HGEDITOR=cat hg config --non-shared
280 280 [ui]
281 281 traceback=true
282 282
283 283 $ cd ../shared1
284 284 $ hg showconfig ui.traceback
285 285 [1]
286 286
287 287 Unsharing works
288 288
289 289 $ hg unshare
290 290
291 291 Test that source config is added to the shared one after unshare, and the config
292 292 of current repo is still respected over the config which came from source config
293 293 $ cd ../cloned
294 294 $ hg push ../shared1
295 295 pushing to ../shared1
296 296 searching for changes
297 297 adding changesets
298 298 adding manifests
299 299 adding file changes
300 300 error: pretxnchangegroup.reject_merge_commits hook failed: bcde3522682d rejected as merge on the same branch. Please consider rebase.
301 301 transaction abort!
302 302 rollback completed
303 303 abort: bcde3522682d rejected as merge on the same branch. Please consider rebase.
304 304 [255]
305 305 $ hg showconfig ui.curses -R ../shared1
306 306 false
307 307
308 308 $ cd ../
309 309
310 310 Test that upgrading using debugupgraderepo works
311 311 =================================================
312 312
313 313 $ hg init non-share-safe --config format.exp-share-safe=false
314 314 $ cd non-share-safe
315 315 $ hg debugrequirements
316 316 dotencode
317 317 fncache
318 318 generaldelta
319 319 revlogv1
320 320 sparserevlog
321 321 store
322 322 $ echo foo > foo
323 323 $ hg ci -Aqm 'added foo'
324 324 $ echo bar > bar
325 325 $ hg ci -Aqm 'added bar'
326 326
327 327 Create a share before upgrading
328 328
329 329 $ cd ..
330 330 $ hg share non-share-safe nss-share
331 331 updating working directory
332 332 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
333 333 $ hg debugrequirements -R nss-share
334 334 dotencode
335 335 fncache
336 336 generaldelta
337 337 revlogv1
338 338 shared
339 339 sparserevlog
340 340 store
341 341 $ cd non-share-safe
342 342
343 343 Upgrade
344 344
345 345 $ hg debugupgraderepo -q
346 346 requirements
347 347 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
348 348 added: exp-sharesafe
349 349
350 350 processed revlogs:
351 351 - all-filelogs
352 352 - changelog
353 353 - manifest
354 354
355 355 $ hg debugupgraderepo --run -q
356 356 upgrade will perform the following actions:
357 357
358 358 requirements
359 359 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
360 360 added: exp-sharesafe
361 361
362 362 processed revlogs:
363 363 - all-filelogs
364 364 - changelog
365 365 - manifest
366 366
367 367 repository upgraded to share safe mode, existing shares will still work in old non-safe mode. Re-share existing shares to use them in safe mode New shares will be created in safe mode.
368 368
369 369 $ hg debugrequirements
370 370 dotencode
371 371 exp-sharesafe
372 372 fncache
373 373 generaldelta
374 374 revlogv1
375 375 sparserevlog
376 376 store
377 377
378 378 $ cat .hg/requires
379 379 exp-sharesafe
380 380
381 381 $ cat .hg/store/requires
382 382 dotencode
383 383 fncache
384 384 generaldelta
385 385 revlogv1
386 386 sparserevlog
387 387 store
388 388
389 389 $ hg log -GT "{node}: {desc}\n"
390 390 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
391 391 |
392 392 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
393 393
394 394
395 395 Make sure existing shares dont work with default config
396 396
397 397 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
398 398 abort: version mismatch: source uses share-safe functionality while the current share does not
399 399 [255]
400 400
401 401
402 402 Create a safe share from upgrade one
403 403
404 404 $ cd ..
405 405 $ hg share non-share-safe ss-share
406 406 updating working directory
407 407 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 408 $ cd ss-share
409 409 $ hg log -GT "{node}: {desc}\n"
410 410 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
411 411 |
412 412 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
413 413
414 414 $ cd ../non-share-safe
415 415
416 416 Test that downgrading works too
417 417
418 418 $ cat >> $HGRCPATH <<EOF
419 419 > [extensions]
420 420 > share =
421 421 > [format]
422 422 > exp-share-safe = False
423 423 > EOF
424 424
425 425 $ hg debugupgraderepo -q
426 426 requirements
427 427 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
428 428 removed: exp-sharesafe
429 429
430 430 processed revlogs:
431 431 - all-filelogs
432 432 - changelog
433 433 - manifest
434 434
435 435 $ hg debugupgraderepo -q --run
436 436 upgrade will perform the following actions:
437 437
438 438 requirements
439 439 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
440 440 removed: exp-sharesafe
441 441
442 442 processed revlogs:
443 443 - all-filelogs
444 444 - changelog
445 445 - manifest
446 446
447 447 repository downgraded to not use share safe mode, existing shares will not work and needs to be reshared.
448 448
449 449 $ hg debugrequirements
450 450 dotencode
451 451 fncache
452 452 generaldelta
453 453 revlogv1
454 454 sparserevlog
455 455 store
456 456
457 457 $ cat .hg/requires
458 458 dotencode
459 459 fncache
460 460 generaldelta
461 461 revlogv1
462 462 sparserevlog
463 463 store
464 464
465 465 $ test -f .hg/store/requires
466 466 [1]
467 467
468 468 $ hg log -GT "{node}: {desc}\n"
469 469 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
470 470 |
471 471 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
472 472
473 473
474 474 Make sure existing shares still works
475 475
476 476 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
477 477 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
478 478 |
479 479 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
480 480
481 481
482 482 $ hg log -GT "{node}: {desc}\n" -R ../ss-share
483 483 abort: share source does not support exp-sharesafe requirement
484 484 [255]
485 485
486 486 Testing automatic downgrade of shares when config is set
487 487
488 488 $ touch ../ss-share/.hg/wlock
489 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config experimental.sharesafe-auto-downgrade-shares=true
489 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config share.safe-mismatch.source-not-safe=downgrade-abort
490 490 abort: failed to downgrade share, got error: Lock held
491 491 [255]
492 492 $ rm ../ss-share/.hg/wlock
493 493
494 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config experimental.sharesafe-auto-downgrade-shares=true
494 $ hg log -GT "{node}: {desc}\n" -R ../ss-share --config share.safe-mismatch.source-not-safe=downgrade-abort
495 495 repository downgraded to not use share-safe mode
496 496 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
497 497 |
498 498 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
499 499
500 500
501 501 $ hg log -GT "{node}: {desc}\n" -R ../ss-share
502 502 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
503 503 |
504 504 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
505 505
506 506
507 507
508 508 Testing automatic upgrade of shares when config is set
509 509
510 510 $ hg debugupgraderepo -q --run --config format.exp-share-safe=True
511 511 upgrade will perform the following actions:
512 512
513 513 requirements
514 514 preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
515 515 added: exp-sharesafe
516 516
517 517 processed revlogs:
518 518 - all-filelogs
519 519 - changelog
520 520 - manifest
521 521
522 522 repository upgraded to share safe mode, existing shares will still work in old non-safe mode. Re-share existing shares to use them in safe mode New shares will be created in safe mode.
523 523 $ hg debugrequirements
524 524 dotencode
525 525 exp-sharesafe
526 526 fncache
527 527 generaldelta
528 528 revlogv1
529 529 sparserevlog
530 530 store
531 531 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
532 532 abort: version mismatch: source uses share-safe functionality while the current share does not
533 533 [255]
534 534
535 535 Check that if lock is taken, upgrade fails but read operation are successful
536 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgra
537 abort: share-safe mismatch with source.
538 Unrecognized value 'upgra' of `share.safe-mismatch.source-safe` set.
539 (run `hg help config.share.safe-mismatch.source-safe`)
540 [255]
536 541 $ touch ../nss-share/.hg/wlock
537 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config experimental.sharesafe-auto-upgrade-shares=true
542 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-allow
538 543 failed to upgrade share, got error: Lock held
539 544 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
540 545 |
541 546 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
542 547
543 548
544 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config experimental.sharesafe-auto-upgrade-shares=true --config experimental.sharesafe-warn-outdated-shares=false
549 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-allow --config experimental.sharesafe-warn-outdated-shares=false
545 550 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
546 551 |
547 552 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
548 553
549 554
550 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config experimental.sharesafe-auto-upgrade-shares=true --config experimental.sharesafe-auto-upgrade-fail-error=true
555 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-abort
551 556 abort: failed to upgrade share, got error: Lock held
552 557 [255]
553 558
554 559 $ rm ../nss-share/.hg/wlock
555 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config experimental.sharesafe-auto-upgrade-shares=true
560 $ hg log -GT "{node}: {desc}\n" -R ../nss-share --config share.safe-mismatch.source-safe=upgrade-abort
556 561 repository upgraded to use share-safe mode
557 562 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
558 563 |
559 564 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
560 565
561 566
562 567 Test that unshare works
563 568
564 569 $ hg unshare -R ../nss-share
565 570 $ hg log -GT "{node}: {desc}\n" -R ../nss-share
566 571 @ f63db81e6dde1d9c78814167f77fb1fb49283f4f: added bar
567 572 |
568 573 o f3ba8b99bb6f897c87bbc1c07b75c6ddf43a4f77: added foo
569 574
General Comments 0
You need to be logged in to leave comments. Login now