##// END OF EJS Templates
filemerge: add configs to disable some or all partial merge tools...
Martin von Zweigbergk -
r50060:7af798e4 default
parent child Browse files
Show More
@@ -1,2772 +1,2786 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
9 9 import functools
10 10 import re
11 11
12 12 from . import (
13 13 encoding,
14 14 error,
15 15 )
16 16
17 17
18 18 def loadconfigtable(ui, extname, configtable):
19 19 """update config item known to the ui with the extension ones"""
20 20 for section, items in sorted(configtable.items()):
21 21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 22 knownkeys = set(knownitems)
23 23 newkeys = set(items)
24 24 for key in sorted(knownkeys & newkeys):
25 25 msg = b"extension '%s' overwrite config item '%s.%s'"
26 26 msg %= (extname, section, key)
27 27 ui.develwarn(msg, config=b'warn-config')
28 28
29 29 knownitems.update(items)
30 30
31 31
32 32 class configitem:
33 33 """represent a known config item
34 34
35 35 :section: the official config section where to find this item,
36 36 :name: the official name within the section,
37 37 :default: default value for this item,
38 38 :alias: optional list of tuples as alternatives,
39 39 :generic: this is a generic definition, match name using regular expression.
40 40 """
41 41
42 42 def __init__(
43 43 self,
44 44 section,
45 45 name,
46 46 default=None,
47 47 alias=(),
48 48 generic=False,
49 49 priority=0,
50 50 experimental=False,
51 51 ):
52 52 self.section = section
53 53 self.name = name
54 54 self.default = default
55 55 self.alias = list(alias)
56 56 self.generic = generic
57 57 self.priority = priority
58 58 self.experimental = experimental
59 59 self._re = None
60 60 if generic:
61 61 self._re = re.compile(self.name)
62 62
63 63
64 64 class itemregister(dict):
65 65 """A specialized dictionary that can handle wild-card selection"""
66 66
67 67 def __init__(self):
68 68 super(itemregister, self).__init__()
69 69 self._generics = set()
70 70
71 71 def update(self, other):
72 72 super(itemregister, self).update(other)
73 73 self._generics.update(other._generics)
74 74
75 75 def __setitem__(self, key, item):
76 76 super(itemregister, self).__setitem__(key, item)
77 77 if item.generic:
78 78 self._generics.add(item)
79 79
80 80 def get(self, key):
81 81 baseitem = super(itemregister, self).get(key)
82 82 if baseitem is not None and not baseitem.generic:
83 83 return baseitem
84 84
85 85 # search for a matching generic item
86 86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 87 for item in generics:
88 88 # we use 'match' instead of 'search' to make the matching simpler
89 89 # for people unfamiliar with regular expression. Having the match
90 90 # rooted to the start of the string will produce less surprising
91 91 # result for user writing simple regex for sub-attribute.
92 92 #
93 93 # For example using "color\..*" match produces an unsurprising
94 94 # result, while using search could suddenly match apparently
95 95 # unrelated configuration that happens to contains "color."
96 96 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 97 # some match to avoid the need to prefix most pattern with "^".
98 98 # The "^" seems more error prone.
99 99 if item._re.match(key):
100 100 return item
101 101
102 102 return None
103 103
104 104
105 105 coreitems = {}
106 106
107 107
108 108 def _register(configtable, *args, **kwargs):
109 109 item = configitem(*args, **kwargs)
110 110 section = configtable.setdefault(item.section, itemregister())
111 111 if item.name in section:
112 112 msg = b"duplicated config item registration for '%s.%s'"
113 113 raise error.ProgrammingError(msg % (item.section, item.name))
114 114 section[item.name] = item
115 115
116 116
117 117 # special value for case where the default is derived from other values
118 118 dynamicdefault = object()
119 119
120 120 # Registering actual config items
121 121
122 122
123 123 def getitemregister(configtable):
124 124 f = functools.partial(_register, configtable)
125 125 # export pseudo enum as configitem.*
126 126 f.dynamicdefault = dynamicdefault
127 127 return f
128 128
129 129
130 130 coreconfigitem = getitemregister(coreitems)
131 131
132 132
133 133 def _registerdiffopts(section, configprefix=b''):
134 134 coreconfigitem(
135 135 section,
136 136 configprefix + b'nodates',
137 137 default=False,
138 138 )
139 139 coreconfigitem(
140 140 section,
141 141 configprefix + b'showfunc',
142 142 default=False,
143 143 )
144 144 coreconfigitem(
145 145 section,
146 146 configprefix + b'unified',
147 147 default=None,
148 148 )
149 149 coreconfigitem(
150 150 section,
151 151 configprefix + b'git',
152 152 default=False,
153 153 )
154 154 coreconfigitem(
155 155 section,
156 156 configprefix + b'ignorews',
157 157 default=False,
158 158 )
159 159 coreconfigitem(
160 160 section,
161 161 configprefix + b'ignorewsamount',
162 162 default=False,
163 163 )
164 164 coreconfigitem(
165 165 section,
166 166 configprefix + b'ignoreblanklines',
167 167 default=False,
168 168 )
169 169 coreconfigitem(
170 170 section,
171 171 configprefix + b'ignorewseol',
172 172 default=False,
173 173 )
174 174 coreconfigitem(
175 175 section,
176 176 configprefix + b'nobinary',
177 177 default=False,
178 178 )
179 179 coreconfigitem(
180 180 section,
181 181 configprefix + b'noprefix',
182 182 default=False,
183 183 )
184 184 coreconfigitem(
185 185 section,
186 186 configprefix + b'word-diff',
187 187 default=False,
188 188 )
189 189
190 190
191 191 coreconfigitem(
192 192 b'alias',
193 193 b'.*',
194 194 default=dynamicdefault,
195 195 generic=True,
196 196 )
197 197 coreconfigitem(
198 198 b'auth',
199 199 b'cookiefile',
200 200 default=None,
201 201 )
202 202 _registerdiffopts(section=b'annotate')
203 203 # bookmarks.pushing: internal hack for discovery
204 204 coreconfigitem(
205 205 b'bookmarks',
206 206 b'pushing',
207 207 default=list,
208 208 )
209 209 # bundle.mainreporoot: internal hack for bundlerepo
210 210 coreconfigitem(
211 211 b'bundle',
212 212 b'mainreporoot',
213 213 default=b'',
214 214 )
215 215 coreconfigitem(
216 216 b'censor',
217 217 b'policy',
218 218 default=b'abort',
219 219 experimental=True,
220 220 )
221 221 coreconfigitem(
222 222 b'chgserver',
223 223 b'idletimeout',
224 224 default=3600,
225 225 )
226 226 coreconfigitem(
227 227 b'chgserver',
228 228 b'skiphash',
229 229 default=False,
230 230 )
231 231 coreconfigitem(
232 232 b'cmdserver',
233 233 b'log',
234 234 default=None,
235 235 )
236 236 coreconfigitem(
237 237 b'cmdserver',
238 238 b'max-log-files',
239 239 default=7,
240 240 )
241 241 coreconfigitem(
242 242 b'cmdserver',
243 243 b'max-log-size',
244 244 default=b'1 MB',
245 245 )
246 246 coreconfigitem(
247 247 b'cmdserver',
248 248 b'max-repo-cache',
249 249 default=0,
250 250 experimental=True,
251 251 )
252 252 coreconfigitem(
253 253 b'cmdserver',
254 254 b'message-encodings',
255 255 default=list,
256 256 )
257 257 coreconfigitem(
258 258 b'cmdserver',
259 259 b'track-log',
260 260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 261 )
262 262 coreconfigitem(
263 263 b'cmdserver',
264 264 b'shutdown-on-interrupt',
265 265 default=True,
266 266 )
267 267 coreconfigitem(
268 268 b'color',
269 269 b'.*',
270 270 default=None,
271 271 generic=True,
272 272 )
273 273 coreconfigitem(
274 274 b'color',
275 275 b'mode',
276 276 default=b'auto',
277 277 )
278 278 coreconfigitem(
279 279 b'color',
280 280 b'pagermode',
281 281 default=dynamicdefault,
282 282 )
283 283 coreconfigitem(
284 284 b'command-templates',
285 285 b'graphnode',
286 286 default=None,
287 287 alias=[(b'ui', b'graphnodetemplate')],
288 288 )
289 289 coreconfigitem(
290 290 b'command-templates',
291 291 b'log',
292 292 default=None,
293 293 alias=[(b'ui', b'logtemplate')],
294 294 )
295 295 coreconfigitem(
296 296 b'command-templates',
297 297 b'mergemarker',
298 298 default=(
299 299 b'{node|short} '
300 300 b'{ifeq(tags, "tip", "", '
301 301 b'ifeq(tags, "", "", "{tags} "))}'
302 302 b'{if(bookmarks, "{bookmarks} ")}'
303 303 b'{ifeq(branch, "default", "", "{branch} ")}'
304 304 b'- {author|user}: {desc|firstline}'
305 305 ),
306 306 alias=[(b'ui', b'mergemarkertemplate')],
307 307 )
308 308 coreconfigitem(
309 309 b'command-templates',
310 310 b'pre-merge-tool-output',
311 311 default=None,
312 312 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 313 )
314 314 coreconfigitem(
315 315 b'command-templates',
316 316 b'oneline-summary',
317 317 default=None,
318 318 )
319 319 coreconfigitem(
320 320 b'command-templates',
321 321 b'oneline-summary.*',
322 322 default=dynamicdefault,
323 323 generic=True,
324 324 )
325 325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 326 coreconfigitem(
327 327 b'commands',
328 328 b'commit.post-status',
329 329 default=False,
330 330 )
331 331 coreconfigitem(
332 332 b'commands',
333 333 b'grep.all-files',
334 334 default=False,
335 335 experimental=True,
336 336 )
337 337 coreconfigitem(
338 338 b'commands',
339 339 b'merge.require-rev',
340 340 default=False,
341 341 )
342 342 coreconfigitem(
343 343 b'commands',
344 344 b'push.require-revs',
345 345 default=False,
346 346 )
347 347 coreconfigitem(
348 348 b'commands',
349 349 b'resolve.confirm',
350 350 default=False,
351 351 )
352 352 coreconfigitem(
353 353 b'commands',
354 354 b'resolve.explicit-re-merge',
355 355 default=False,
356 356 )
357 357 coreconfigitem(
358 358 b'commands',
359 359 b'resolve.mark-check',
360 360 default=b'none',
361 361 )
362 362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 363 coreconfigitem(
364 364 b'commands',
365 365 b'show.aliasprefix',
366 366 default=list,
367 367 )
368 368 coreconfigitem(
369 369 b'commands',
370 370 b'status.relative',
371 371 default=False,
372 372 )
373 373 coreconfigitem(
374 374 b'commands',
375 375 b'status.skipstates',
376 376 default=[],
377 377 experimental=True,
378 378 )
379 379 coreconfigitem(
380 380 b'commands',
381 381 b'status.terse',
382 382 default=b'',
383 383 )
384 384 coreconfigitem(
385 385 b'commands',
386 386 b'status.verbose',
387 387 default=False,
388 388 )
389 389 coreconfigitem(
390 390 b'commands',
391 391 b'update.check',
392 392 default=None,
393 393 )
394 394 coreconfigitem(
395 395 b'commands',
396 396 b'update.requiredest',
397 397 default=False,
398 398 )
399 399 coreconfigitem(
400 400 b'committemplate',
401 401 b'.*',
402 402 default=None,
403 403 generic=True,
404 404 )
405 405 coreconfigitem(
406 406 b'convert',
407 407 b'bzr.saverev',
408 408 default=True,
409 409 )
410 410 coreconfigitem(
411 411 b'convert',
412 412 b'cvsps.cache',
413 413 default=True,
414 414 )
415 415 coreconfigitem(
416 416 b'convert',
417 417 b'cvsps.fuzz',
418 418 default=60,
419 419 )
420 420 coreconfigitem(
421 421 b'convert',
422 422 b'cvsps.logencoding',
423 423 default=None,
424 424 )
425 425 coreconfigitem(
426 426 b'convert',
427 427 b'cvsps.mergefrom',
428 428 default=None,
429 429 )
430 430 coreconfigitem(
431 431 b'convert',
432 432 b'cvsps.mergeto',
433 433 default=None,
434 434 )
435 435 coreconfigitem(
436 436 b'convert',
437 437 b'git.committeractions',
438 438 default=lambda: [b'messagedifferent'],
439 439 )
440 440 coreconfigitem(
441 441 b'convert',
442 442 b'git.extrakeys',
443 443 default=list,
444 444 )
445 445 coreconfigitem(
446 446 b'convert',
447 447 b'git.findcopiesharder',
448 448 default=False,
449 449 )
450 450 coreconfigitem(
451 451 b'convert',
452 452 b'git.remoteprefix',
453 453 default=b'remote',
454 454 )
455 455 coreconfigitem(
456 456 b'convert',
457 457 b'git.renamelimit',
458 458 default=400,
459 459 )
460 460 coreconfigitem(
461 461 b'convert',
462 462 b'git.saverev',
463 463 default=True,
464 464 )
465 465 coreconfigitem(
466 466 b'convert',
467 467 b'git.similarity',
468 468 default=50,
469 469 )
470 470 coreconfigitem(
471 471 b'convert',
472 472 b'git.skipsubmodules',
473 473 default=False,
474 474 )
475 475 coreconfigitem(
476 476 b'convert',
477 477 b'hg.clonebranches',
478 478 default=False,
479 479 )
480 480 coreconfigitem(
481 481 b'convert',
482 482 b'hg.ignoreerrors',
483 483 default=False,
484 484 )
485 485 coreconfigitem(
486 486 b'convert',
487 487 b'hg.preserve-hash',
488 488 default=False,
489 489 )
490 490 coreconfigitem(
491 491 b'convert',
492 492 b'hg.revs',
493 493 default=None,
494 494 )
495 495 coreconfigitem(
496 496 b'convert',
497 497 b'hg.saverev',
498 498 default=False,
499 499 )
500 500 coreconfigitem(
501 501 b'convert',
502 502 b'hg.sourcename',
503 503 default=None,
504 504 )
505 505 coreconfigitem(
506 506 b'convert',
507 507 b'hg.startrev',
508 508 default=None,
509 509 )
510 510 coreconfigitem(
511 511 b'convert',
512 512 b'hg.tagsbranch',
513 513 default=b'default',
514 514 )
515 515 coreconfigitem(
516 516 b'convert',
517 517 b'hg.usebranchnames',
518 518 default=True,
519 519 )
520 520 coreconfigitem(
521 521 b'convert',
522 522 b'ignoreancestorcheck',
523 523 default=False,
524 524 experimental=True,
525 525 )
526 526 coreconfigitem(
527 527 b'convert',
528 528 b'localtimezone',
529 529 default=False,
530 530 )
531 531 coreconfigitem(
532 532 b'convert',
533 533 b'p4.encoding',
534 534 default=dynamicdefault,
535 535 )
536 536 coreconfigitem(
537 537 b'convert',
538 538 b'p4.startrev',
539 539 default=0,
540 540 )
541 541 coreconfigitem(
542 542 b'convert',
543 543 b'skiptags',
544 544 default=False,
545 545 )
546 546 coreconfigitem(
547 547 b'convert',
548 548 b'svn.debugsvnlog',
549 549 default=True,
550 550 )
551 551 coreconfigitem(
552 552 b'convert',
553 553 b'svn.trunk',
554 554 default=None,
555 555 )
556 556 coreconfigitem(
557 557 b'convert',
558 558 b'svn.tags',
559 559 default=None,
560 560 )
561 561 coreconfigitem(
562 562 b'convert',
563 563 b'svn.branches',
564 564 default=None,
565 565 )
566 566 coreconfigitem(
567 567 b'convert',
568 568 b'svn.startrev',
569 569 default=0,
570 570 )
571 571 coreconfigitem(
572 572 b'convert',
573 573 b'svn.dangerous-set-commit-dates',
574 574 default=False,
575 575 )
576 576 coreconfigitem(
577 577 b'debug',
578 578 b'dirstate.delaywrite',
579 579 default=0,
580 580 )
581 581 coreconfigitem(
582 582 b'debug',
583 583 b'revlog.verifyposition.changelog',
584 584 default=b'',
585 585 )
586 586 coreconfigitem(
587 587 b'defaults',
588 588 b'.*',
589 589 default=None,
590 590 generic=True,
591 591 )
592 592 coreconfigitem(
593 593 b'devel',
594 594 b'all-warnings',
595 595 default=False,
596 596 )
597 597 coreconfigitem(
598 598 b'devel',
599 599 b'bundle2.debug',
600 600 default=False,
601 601 )
602 602 coreconfigitem(
603 603 b'devel',
604 604 b'bundle.delta',
605 605 default=b'',
606 606 )
607 607 coreconfigitem(
608 608 b'devel',
609 609 b'cache-vfs',
610 610 default=None,
611 611 )
612 612 coreconfigitem(
613 613 b'devel',
614 614 b'check-locks',
615 615 default=False,
616 616 )
617 617 coreconfigitem(
618 618 b'devel',
619 619 b'check-relroot',
620 620 default=False,
621 621 )
622 622 # Track copy information for all file, not just "added" one (very slow)
623 623 coreconfigitem(
624 624 b'devel',
625 625 b'copy-tracing.trace-all-files',
626 626 default=False,
627 627 )
628 628 coreconfigitem(
629 629 b'devel',
630 630 b'default-date',
631 631 default=None,
632 632 )
633 633 coreconfigitem(
634 634 b'devel',
635 635 b'deprec-warn',
636 636 default=False,
637 637 )
638 638 coreconfigitem(
639 639 b'devel',
640 640 b'disableloaddefaultcerts',
641 641 default=False,
642 642 )
643 643 coreconfigitem(
644 644 b'devel',
645 645 b'warn-empty-changegroup',
646 646 default=False,
647 647 )
648 648 coreconfigitem(
649 649 b'devel',
650 650 b'legacy.exchange',
651 651 default=list,
652 652 )
653 653 # When True, revlogs use a special reference version of the nodemap, that is not
654 654 # performant but is "known" to behave properly.
655 655 coreconfigitem(
656 656 b'devel',
657 657 b'persistent-nodemap',
658 658 default=False,
659 659 )
660 660 coreconfigitem(
661 661 b'devel',
662 662 b'servercafile',
663 663 default=b'',
664 664 )
665 665 coreconfigitem(
666 666 b'devel',
667 667 b'serverexactprotocol',
668 668 default=b'',
669 669 )
670 670 coreconfigitem(
671 671 b'devel',
672 672 b'serverrequirecert',
673 673 default=False,
674 674 )
675 675 coreconfigitem(
676 676 b'devel',
677 677 b'strip-obsmarkers',
678 678 default=True,
679 679 )
680 680 coreconfigitem(
681 681 b'devel',
682 682 b'warn-config',
683 683 default=None,
684 684 )
685 685 coreconfigitem(
686 686 b'devel',
687 687 b'warn-config-default',
688 688 default=None,
689 689 )
690 690 coreconfigitem(
691 691 b'devel',
692 692 b'user.obsmarker',
693 693 default=None,
694 694 )
695 695 coreconfigitem(
696 696 b'devel',
697 697 b'warn-config-unknown',
698 698 default=None,
699 699 )
700 700 coreconfigitem(
701 701 b'devel',
702 702 b'debug.copies',
703 703 default=False,
704 704 )
705 705 coreconfigitem(
706 706 b'devel',
707 707 b'copy-tracing.multi-thread',
708 708 default=True,
709 709 )
710 710 coreconfigitem(
711 711 b'devel',
712 712 b'debug.extensions',
713 713 default=False,
714 714 )
715 715 coreconfigitem(
716 716 b'devel',
717 717 b'debug.repo-filters',
718 718 default=False,
719 719 )
720 720 coreconfigitem(
721 721 b'devel',
722 722 b'debug.peer-request',
723 723 default=False,
724 724 )
725 725 # If discovery.exchange-heads is False, the discovery will not start with
726 726 # remote head fetching and local head querying.
727 727 coreconfigitem(
728 728 b'devel',
729 729 b'discovery.exchange-heads',
730 730 default=True,
731 731 )
732 732 # If discovery.grow-sample is False, the sample size used in set discovery will
733 733 # not be increased through the process
734 734 coreconfigitem(
735 735 b'devel',
736 736 b'discovery.grow-sample',
737 737 default=True,
738 738 )
739 739 # When discovery.grow-sample.dynamic is True, the default, the sample size is
740 740 # adapted to the shape of the undecided set (it is set to the max of:
741 741 # <target-size>, len(roots(undecided)), len(heads(undecided)
742 742 coreconfigitem(
743 743 b'devel',
744 744 b'discovery.grow-sample.dynamic',
745 745 default=True,
746 746 )
747 747 # discovery.grow-sample.rate control the rate at which the sample grow
748 748 coreconfigitem(
749 749 b'devel',
750 750 b'discovery.grow-sample.rate',
751 751 default=1.05,
752 752 )
753 753 # If discovery.randomize is False, random sampling during discovery are
754 754 # deterministic. It is meant for integration tests.
755 755 coreconfigitem(
756 756 b'devel',
757 757 b'discovery.randomize',
758 758 default=True,
759 759 )
760 760 # Control the initial size of the discovery sample
761 761 coreconfigitem(
762 762 b'devel',
763 763 b'discovery.sample-size',
764 764 default=200,
765 765 )
766 766 # Control the initial size of the discovery for initial change
767 767 coreconfigitem(
768 768 b'devel',
769 769 b'discovery.sample-size.initial',
770 770 default=100,
771 771 )
772 772 _registerdiffopts(section=b'diff')
773 773 coreconfigitem(
774 774 b'diff',
775 775 b'merge',
776 776 default=False,
777 777 experimental=True,
778 778 )
779 779 coreconfigitem(
780 780 b'email',
781 781 b'bcc',
782 782 default=None,
783 783 )
784 784 coreconfigitem(
785 785 b'email',
786 786 b'cc',
787 787 default=None,
788 788 )
789 789 coreconfigitem(
790 790 b'email',
791 791 b'charsets',
792 792 default=list,
793 793 )
794 794 coreconfigitem(
795 795 b'email',
796 796 b'from',
797 797 default=None,
798 798 )
799 799 coreconfigitem(
800 800 b'email',
801 801 b'method',
802 802 default=b'smtp',
803 803 )
804 804 coreconfigitem(
805 805 b'email',
806 806 b'reply-to',
807 807 default=None,
808 808 )
809 809 coreconfigitem(
810 810 b'email',
811 811 b'to',
812 812 default=None,
813 813 )
814 814 coreconfigitem(
815 815 b'experimental',
816 816 b'archivemetatemplate',
817 817 default=dynamicdefault,
818 818 )
819 819 coreconfigitem(
820 820 b'experimental',
821 821 b'auto-publish',
822 822 default=b'publish',
823 823 )
824 824 coreconfigitem(
825 825 b'experimental',
826 826 b'bundle-phases',
827 827 default=False,
828 828 )
829 829 coreconfigitem(
830 830 b'experimental',
831 831 b'bundle2-advertise',
832 832 default=True,
833 833 )
834 834 coreconfigitem(
835 835 b'experimental',
836 836 b'bundle2-output-capture',
837 837 default=False,
838 838 )
839 839 coreconfigitem(
840 840 b'experimental',
841 841 b'bundle2.pushback',
842 842 default=False,
843 843 )
844 844 coreconfigitem(
845 845 b'experimental',
846 846 b'bundle2lazylocking',
847 847 default=False,
848 848 )
849 849 coreconfigitem(
850 850 b'experimental',
851 851 b'bundlecomplevel',
852 852 default=None,
853 853 )
854 854 coreconfigitem(
855 855 b'experimental',
856 856 b'bundlecomplevel.bzip2',
857 857 default=None,
858 858 )
859 859 coreconfigitem(
860 860 b'experimental',
861 861 b'bundlecomplevel.gzip',
862 862 default=None,
863 863 )
864 864 coreconfigitem(
865 865 b'experimental',
866 866 b'bundlecomplevel.none',
867 867 default=None,
868 868 )
869 869 coreconfigitem(
870 870 b'experimental',
871 871 b'bundlecomplevel.zstd',
872 872 default=None,
873 873 )
874 874 coreconfigitem(
875 875 b'experimental',
876 876 b'bundlecompthreads',
877 877 default=None,
878 878 )
879 879 coreconfigitem(
880 880 b'experimental',
881 881 b'bundlecompthreads.bzip2',
882 882 default=None,
883 883 )
884 884 coreconfigitem(
885 885 b'experimental',
886 886 b'bundlecompthreads.gzip',
887 887 default=None,
888 888 )
889 889 coreconfigitem(
890 890 b'experimental',
891 891 b'bundlecompthreads.none',
892 892 default=None,
893 893 )
894 894 coreconfigitem(
895 895 b'experimental',
896 896 b'bundlecompthreads.zstd',
897 897 default=None,
898 898 )
899 899 coreconfigitem(
900 900 b'experimental',
901 901 b'changegroup3',
902 902 default=False,
903 903 )
904 904 coreconfigitem(
905 905 b'experimental',
906 906 b'changegroup4',
907 907 default=False,
908 908 )
909 909 coreconfigitem(
910 910 b'experimental',
911 911 b'cleanup-as-archived',
912 912 default=False,
913 913 )
914 914 coreconfigitem(
915 915 b'experimental',
916 916 b'clientcompressionengines',
917 917 default=list,
918 918 )
919 919 coreconfigitem(
920 920 b'experimental',
921 921 b'copytrace',
922 922 default=b'on',
923 923 )
924 924 coreconfigitem(
925 925 b'experimental',
926 926 b'copytrace.movecandidateslimit',
927 927 default=100,
928 928 )
929 929 coreconfigitem(
930 930 b'experimental',
931 931 b'copytrace.sourcecommitlimit',
932 932 default=100,
933 933 )
934 934 coreconfigitem(
935 935 b'experimental',
936 936 b'copies.read-from',
937 937 default=b"filelog-only",
938 938 )
939 939 coreconfigitem(
940 940 b'experimental',
941 941 b'copies.write-to',
942 942 default=b'filelog-only',
943 943 )
944 944 coreconfigitem(
945 945 b'experimental',
946 946 b'crecordtest',
947 947 default=None,
948 948 )
949 949 coreconfigitem(
950 950 b'experimental',
951 951 b'directaccess',
952 952 default=False,
953 953 )
954 954 coreconfigitem(
955 955 b'experimental',
956 956 b'directaccess.revnums',
957 957 default=False,
958 958 )
959 959 coreconfigitem(
960 960 b'experimental',
961 961 b'editortmpinhg',
962 962 default=False,
963 963 )
964 964 coreconfigitem(
965 965 b'experimental',
966 966 b'evolution',
967 967 default=list,
968 968 )
969 969 coreconfigitem(
970 970 b'experimental',
971 971 b'evolution.allowdivergence',
972 972 default=False,
973 973 alias=[(b'experimental', b'allowdivergence')],
974 974 )
975 975 coreconfigitem(
976 976 b'experimental',
977 977 b'evolution.allowunstable',
978 978 default=None,
979 979 )
980 980 coreconfigitem(
981 981 b'experimental',
982 982 b'evolution.createmarkers',
983 983 default=None,
984 984 )
985 985 coreconfigitem(
986 986 b'experimental',
987 987 b'evolution.effect-flags',
988 988 default=True,
989 989 alias=[(b'experimental', b'effect-flags')],
990 990 )
991 991 coreconfigitem(
992 992 b'experimental',
993 993 b'evolution.exchange',
994 994 default=None,
995 995 )
996 996 coreconfigitem(
997 997 b'experimental',
998 998 b'evolution.bundle-obsmarker',
999 999 default=False,
1000 1000 )
1001 1001 coreconfigitem(
1002 1002 b'experimental',
1003 1003 b'evolution.bundle-obsmarker:mandatory',
1004 1004 default=True,
1005 1005 )
1006 1006 coreconfigitem(
1007 1007 b'experimental',
1008 1008 b'log.topo',
1009 1009 default=False,
1010 1010 )
1011 1011 coreconfigitem(
1012 1012 b'experimental',
1013 1013 b'evolution.report-instabilities',
1014 1014 default=True,
1015 1015 )
1016 1016 coreconfigitem(
1017 1017 b'experimental',
1018 1018 b'evolution.track-operation',
1019 1019 default=True,
1020 1020 )
1021 1021 # repo-level config to exclude a revset visibility
1022 1022 #
1023 1023 # The target use case is to use `share` to expose different subset of the same
1024 1024 # repository, especially server side. See also `server.view`.
1025 1025 coreconfigitem(
1026 1026 b'experimental',
1027 1027 b'extra-filter-revs',
1028 1028 default=None,
1029 1029 )
1030 1030 coreconfigitem(
1031 1031 b'experimental',
1032 1032 b'maxdeltachainspan',
1033 1033 default=-1,
1034 1034 )
1035 1035 # tracks files which were undeleted (merge might delete them but we explicitly
1036 1036 # kept/undeleted them) and creates new filenodes for them
1037 1037 coreconfigitem(
1038 1038 b'experimental',
1039 1039 b'merge-track-salvaged',
1040 1040 default=False,
1041 1041 )
1042 1042 coreconfigitem(
1043 1043 b'experimental',
1044 1044 b'mmapindexthreshold',
1045 1045 default=None,
1046 1046 )
1047 1047 coreconfigitem(
1048 1048 b'experimental',
1049 1049 b'narrow',
1050 1050 default=False,
1051 1051 )
1052 1052 coreconfigitem(
1053 1053 b'experimental',
1054 1054 b'nonnormalparanoidcheck',
1055 1055 default=False,
1056 1056 )
1057 1057 coreconfigitem(
1058 1058 b'experimental',
1059 1059 b'exportableenviron',
1060 1060 default=list,
1061 1061 )
1062 1062 coreconfigitem(
1063 1063 b'experimental',
1064 1064 b'extendedheader.index',
1065 1065 default=None,
1066 1066 )
1067 1067 coreconfigitem(
1068 1068 b'experimental',
1069 1069 b'extendedheader.similarity',
1070 1070 default=False,
1071 1071 )
1072 1072 coreconfigitem(
1073 1073 b'experimental',
1074 1074 b'graphshorten',
1075 1075 default=False,
1076 1076 )
1077 1077 coreconfigitem(
1078 1078 b'experimental',
1079 1079 b'graphstyle.parent',
1080 1080 default=dynamicdefault,
1081 1081 )
1082 1082 coreconfigitem(
1083 1083 b'experimental',
1084 1084 b'graphstyle.missing',
1085 1085 default=dynamicdefault,
1086 1086 )
1087 1087 coreconfigitem(
1088 1088 b'experimental',
1089 1089 b'graphstyle.grandparent',
1090 1090 default=dynamicdefault,
1091 1091 )
1092 1092 coreconfigitem(
1093 1093 b'experimental',
1094 1094 b'hook-track-tags',
1095 1095 default=False,
1096 1096 )
1097 1097 coreconfigitem(
1098 1098 b'experimental',
1099 1099 b'httppostargs',
1100 1100 default=False,
1101 1101 )
1102 1102 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1103 1103 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1104 1104
1105 1105 coreconfigitem(
1106 1106 b'experimental',
1107 1107 b'obsmarkers-exchange-debug',
1108 1108 default=False,
1109 1109 )
1110 1110 coreconfigitem(
1111 1111 b'experimental',
1112 1112 b'remotenames',
1113 1113 default=False,
1114 1114 )
1115 1115 coreconfigitem(
1116 1116 b'experimental',
1117 1117 b'removeemptydirs',
1118 1118 default=True,
1119 1119 )
1120 1120 coreconfigitem(
1121 1121 b'experimental',
1122 1122 b'revert.interactive.select-to-keep',
1123 1123 default=False,
1124 1124 )
1125 1125 coreconfigitem(
1126 1126 b'experimental',
1127 1127 b'revisions.prefixhexnode',
1128 1128 default=False,
1129 1129 )
1130 1130 # "out of experimental" todo list.
1131 1131 #
1132 1132 # * include management of a persistent nodemap in the main docket
1133 1133 # * enforce a "no-truncate" policy for mmap safety
1134 1134 # - for censoring operation
1135 1135 # - for stripping operation
1136 1136 # - for rollback operation
1137 1137 # * proper streaming (race free) of the docket file
1138 1138 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1139 1139 # * Exchange-wise, we will also need to do something more efficient than
1140 1140 # keeping references to the affected revlogs, especially memory-wise when
1141 1141 # rewriting sidedata.
1142 1142 # * introduce a proper solution to reduce the number of filelog related files.
1143 1143 # * use caching for reading sidedata (similar to what we do for data).
1144 1144 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1145 1145 # * Improvement to consider
1146 1146 # - avoid compression header in chunk using the default compression?
1147 1147 # - forbid "inline" compression mode entirely?
1148 1148 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1149 1149 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1150 1150 # - keep track of chain base or size (probably not that useful anymore)
1151 1151 coreconfigitem(
1152 1152 b'experimental',
1153 1153 b'revlogv2',
1154 1154 default=None,
1155 1155 )
1156 1156 coreconfigitem(
1157 1157 b'experimental',
1158 1158 b'revisions.disambiguatewithin',
1159 1159 default=None,
1160 1160 )
1161 1161 coreconfigitem(
1162 1162 b'experimental',
1163 1163 b'rust.index',
1164 1164 default=False,
1165 1165 )
1166 1166 coreconfigitem(
1167 1167 b'experimental',
1168 1168 b'server.filesdata.recommended-batch-size',
1169 1169 default=50000,
1170 1170 )
1171 1171 coreconfigitem(
1172 1172 b'experimental',
1173 1173 b'server.manifestdata.recommended-batch-size',
1174 1174 default=100000,
1175 1175 )
1176 1176 coreconfigitem(
1177 1177 b'experimental',
1178 1178 b'server.stream-narrow-clones',
1179 1179 default=False,
1180 1180 )
1181 1181 coreconfigitem(
1182 1182 b'experimental',
1183 1183 b'single-head-per-branch',
1184 1184 default=False,
1185 1185 )
1186 1186 coreconfigitem(
1187 1187 b'experimental',
1188 1188 b'single-head-per-branch:account-closed-heads',
1189 1189 default=False,
1190 1190 )
1191 1191 coreconfigitem(
1192 1192 b'experimental',
1193 1193 b'single-head-per-branch:public-changes-only',
1194 1194 default=False,
1195 1195 )
1196 1196 coreconfigitem(
1197 1197 b'experimental',
1198 1198 b'sparse-read',
1199 1199 default=False,
1200 1200 )
1201 1201 coreconfigitem(
1202 1202 b'experimental',
1203 1203 b'sparse-read.density-threshold',
1204 1204 default=0.50,
1205 1205 )
1206 1206 coreconfigitem(
1207 1207 b'experimental',
1208 1208 b'sparse-read.min-gap-size',
1209 1209 default=b'65K',
1210 1210 )
1211 1211 coreconfigitem(
1212 1212 b'experimental',
1213 1213 b'treemanifest',
1214 1214 default=False,
1215 1215 )
1216 1216 coreconfigitem(
1217 1217 b'experimental',
1218 1218 b'update.atomic-file',
1219 1219 default=False,
1220 1220 )
1221 1221 coreconfigitem(
1222 1222 b'experimental',
1223 1223 b'web.full-garbage-collection-rate',
1224 1224 default=1, # still forcing a full collection on each request
1225 1225 )
1226 1226 coreconfigitem(
1227 1227 b'experimental',
1228 1228 b'worker.wdir-get-thread-safe',
1229 1229 default=False,
1230 1230 )
1231 1231 coreconfigitem(
1232 1232 b'experimental',
1233 1233 b'worker.repository-upgrade',
1234 1234 default=False,
1235 1235 )
1236 1236 coreconfigitem(
1237 1237 b'experimental',
1238 1238 b'xdiff',
1239 1239 default=False,
1240 1240 )
1241 1241 coreconfigitem(
1242 1242 b'extensions',
1243 1243 b'[^:]*',
1244 1244 default=None,
1245 1245 generic=True,
1246 1246 )
1247 1247 coreconfigitem(
1248 1248 b'extensions',
1249 1249 b'[^:]*:required',
1250 1250 default=False,
1251 1251 generic=True,
1252 1252 )
1253 1253 coreconfigitem(
1254 1254 b'extdata',
1255 1255 b'.*',
1256 1256 default=None,
1257 1257 generic=True,
1258 1258 )
1259 1259 coreconfigitem(
1260 1260 b'format',
1261 1261 b'bookmarks-in-store',
1262 1262 default=False,
1263 1263 )
1264 1264 coreconfigitem(
1265 1265 b'format',
1266 1266 b'chunkcachesize',
1267 1267 default=None,
1268 1268 experimental=True,
1269 1269 )
1270 1270 coreconfigitem(
1271 1271 # Enable this dirstate format *when creating a new repository*.
1272 1272 # Which format to use for existing repos is controlled by .hg/requires
1273 1273 b'format',
1274 1274 b'use-dirstate-v2',
1275 1275 default=False,
1276 1276 experimental=True,
1277 1277 alias=[(b'format', b'exp-rc-dirstate-v2')],
1278 1278 )
1279 1279 coreconfigitem(
1280 1280 b'format',
1281 1281 b'use-dirstate-tracked-hint',
1282 1282 default=False,
1283 1283 experimental=True,
1284 1284 )
1285 1285 coreconfigitem(
1286 1286 b'format',
1287 1287 b'use-dirstate-tracked-hint.version',
1288 1288 default=1,
1289 1289 experimental=True,
1290 1290 )
1291 1291 coreconfigitem(
1292 1292 b'format',
1293 1293 b'dotencode',
1294 1294 default=True,
1295 1295 )
1296 1296 coreconfigitem(
1297 1297 b'format',
1298 1298 b'generaldelta',
1299 1299 default=False,
1300 1300 experimental=True,
1301 1301 )
1302 1302 coreconfigitem(
1303 1303 b'format',
1304 1304 b'manifestcachesize',
1305 1305 default=None,
1306 1306 experimental=True,
1307 1307 )
1308 1308 coreconfigitem(
1309 1309 b'format',
1310 1310 b'maxchainlen',
1311 1311 default=dynamicdefault,
1312 1312 experimental=True,
1313 1313 )
1314 1314 coreconfigitem(
1315 1315 b'format',
1316 1316 b'obsstore-version',
1317 1317 default=None,
1318 1318 )
1319 1319 coreconfigitem(
1320 1320 b'format',
1321 1321 b'sparse-revlog',
1322 1322 default=True,
1323 1323 )
1324 1324 coreconfigitem(
1325 1325 b'format',
1326 1326 b'revlog-compression',
1327 1327 default=lambda: [b'zstd', b'zlib'],
1328 1328 alias=[(b'experimental', b'format.compression')],
1329 1329 )
1330 1330 # Experimental TODOs:
1331 1331 #
1332 1332 # * Same as for revlogv2 (but for the reduction of the number of files)
1333 1333 # * Actually computing the rank of changesets
1334 1334 # * Improvement to investigate
1335 1335 # - storing .hgtags fnode
1336 1336 # - storing branch related identifier
1337 1337
1338 1338 coreconfigitem(
1339 1339 b'format',
1340 1340 b'exp-use-changelog-v2',
1341 1341 default=None,
1342 1342 experimental=True,
1343 1343 )
1344 1344 coreconfigitem(
1345 1345 b'format',
1346 1346 b'usefncache',
1347 1347 default=True,
1348 1348 )
1349 1349 coreconfigitem(
1350 1350 b'format',
1351 1351 b'usegeneraldelta',
1352 1352 default=True,
1353 1353 )
1354 1354 coreconfigitem(
1355 1355 b'format',
1356 1356 b'usestore',
1357 1357 default=True,
1358 1358 )
1359 1359
1360 1360
1361 1361 def _persistent_nodemap_default():
1362 1362 """compute `use-persistent-nodemap` default value
1363 1363
1364 1364 The feature is disabled unless a fast implementation is available.
1365 1365 """
1366 1366 from . import policy
1367 1367
1368 1368 return policy.importrust('revlog') is not None
1369 1369
1370 1370
1371 1371 coreconfigitem(
1372 1372 b'format',
1373 1373 b'use-persistent-nodemap',
1374 1374 default=_persistent_nodemap_default,
1375 1375 )
1376 1376 coreconfigitem(
1377 1377 b'format',
1378 1378 b'exp-use-copies-side-data-changeset',
1379 1379 default=False,
1380 1380 experimental=True,
1381 1381 )
1382 1382 coreconfigitem(
1383 1383 b'format',
1384 1384 b'use-share-safe',
1385 1385 default=True,
1386 1386 )
1387 1387 coreconfigitem(
1388 1388 b'format',
1389 1389 b'internal-phase',
1390 1390 default=False,
1391 1391 experimental=True,
1392 1392 )
1393 1393 coreconfigitem(
1394 1394 b'fsmonitor',
1395 1395 b'warn_when_unused',
1396 1396 default=True,
1397 1397 )
1398 1398 coreconfigitem(
1399 1399 b'fsmonitor',
1400 1400 b'warn_update_file_count',
1401 1401 default=50000,
1402 1402 )
1403 1403 coreconfigitem(
1404 1404 b'fsmonitor',
1405 1405 b'warn_update_file_count_rust',
1406 1406 default=400000,
1407 1407 )
1408 1408 coreconfigitem(
1409 1409 b'help',
1410 1410 br'hidden-command\..*',
1411 1411 default=False,
1412 1412 generic=True,
1413 1413 )
1414 1414 coreconfigitem(
1415 1415 b'help',
1416 1416 br'hidden-topic\..*',
1417 1417 default=False,
1418 1418 generic=True,
1419 1419 )
1420 1420 coreconfigitem(
1421 1421 b'hooks',
1422 1422 b'[^:]*',
1423 1423 default=dynamicdefault,
1424 1424 generic=True,
1425 1425 )
1426 1426 coreconfigitem(
1427 1427 b'hooks',
1428 1428 b'.*:run-with-plain',
1429 1429 default=True,
1430 1430 generic=True,
1431 1431 )
1432 1432 coreconfigitem(
1433 1433 b'hgweb-paths',
1434 1434 b'.*',
1435 1435 default=list,
1436 1436 generic=True,
1437 1437 )
1438 1438 coreconfigitem(
1439 1439 b'hostfingerprints',
1440 1440 b'.*',
1441 1441 default=list,
1442 1442 generic=True,
1443 1443 )
1444 1444 coreconfigitem(
1445 1445 b'hostsecurity',
1446 1446 b'ciphers',
1447 1447 default=None,
1448 1448 )
1449 1449 coreconfigitem(
1450 1450 b'hostsecurity',
1451 1451 b'minimumprotocol',
1452 1452 default=dynamicdefault,
1453 1453 )
1454 1454 coreconfigitem(
1455 1455 b'hostsecurity',
1456 1456 b'.*:minimumprotocol$',
1457 1457 default=dynamicdefault,
1458 1458 generic=True,
1459 1459 )
1460 1460 coreconfigitem(
1461 1461 b'hostsecurity',
1462 1462 b'.*:ciphers$',
1463 1463 default=dynamicdefault,
1464 1464 generic=True,
1465 1465 )
1466 1466 coreconfigitem(
1467 1467 b'hostsecurity',
1468 1468 b'.*:fingerprints$',
1469 1469 default=list,
1470 1470 generic=True,
1471 1471 )
1472 1472 coreconfigitem(
1473 1473 b'hostsecurity',
1474 1474 b'.*:verifycertsfile$',
1475 1475 default=None,
1476 1476 generic=True,
1477 1477 )
1478 1478
1479 1479 coreconfigitem(
1480 1480 b'http_proxy',
1481 1481 b'always',
1482 1482 default=False,
1483 1483 )
1484 1484 coreconfigitem(
1485 1485 b'http_proxy',
1486 1486 b'host',
1487 1487 default=None,
1488 1488 )
1489 1489 coreconfigitem(
1490 1490 b'http_proxy',
1491 1491 b'no',
1492 1492 default=list,
1493 1493 )
1494 1494 coreconfigitem(
1495 1495 b'http_proxy',
1496 1496 b'passwd',
1497 1497 default=None,
1498 1498 )
1499 1499 coreconfigitem(
1500 1500 b'http_proxy',
1501 1501 b'user',
1502 1502 default=None,
1503 1503 )
1504 1504
1505 1505 coreconfigitem(
1506 1506 b'http',
1507 1507 b'timeout',
1508 1508 default=None,
1509 1509 )
1510 1510
1511 1511 coreconfigitem(
1512 1512 b'logtoprocess',
1513 1513 b'commandexception',
1514 1514 default=None,
1515 1515 )
1516 1516 coreconfigitem(
1517 1517 b'logtoprocess',
1518 1518 b'commandfinish',
1519 1519 default=None,
1520 1520 )
1521 1521 coreconfigitem(
1522 1522 b'logtoprocess',
1523 1523 b'command',
1524 1524 default=None,
1525 1525 )
1526 1526 coreconfigitem(
1527 1527 b'logtoprocess',
1528 1528 b'develwarn',
1529 1529 default=None,
1530 1530 )
1531 1531 coreconfigitem(
1532 1532 b'logtoprocess',
1533 1533 b'uiblocked',
1534 1534 default=None,
1535 1535 )
1536 1536 coreconfigitem(
1537 1537 b'merge',
1538 1538 b'checkunknown',
1539 1539 default=b'abort',
1540 1540 )
1541 1541 coreconfigitem(
1542 1542 b'merge',
1543 1543 b'checkignored',
1544 1544 default=b'abort',
1545 1545 )
1546 1546 coreconfigitem(
1547 1547 b'experimental',
1548 1548 b'merge.checkpathconflicts',
1549 1549 default=False,
1550 1550 )
1551 1551 coreconfigitem(
1552 1552 b'merge',
1553 1553 b'followcopies',
1554 1554 default=True,
1555 1555 )
1556 1556 coreconfigitem(
1557 1557 b'merge',
1558 1558 b'on-failure',
1559 1559 default=b'continue',
1560 1560 )
1561 1561 coreconfigitem(
1562 1562 b'merge',
1563 1563 b'preferancestor',
1564 1564 default=lambda: [b'*'],
1565 1565 experimental=True,
1566 1566 )
1567 1567 coreconfigitem(
1568 1568 b'merge',
1569 1569 b'strict-capability-check',
1570 1570 default=False,
1571 1571 )
1572 1572 coreconfigitem(
1573 b'merge',
1574 b'disable-partial-tools',
1575 default=False,
1576 experimental=True,
1577 )
1578 coreconfigitem(
1573 1579 b'partial-merge-tools',
1574 1580 b'.*',
1575 1581 default=None,
1576 1582 generic=True,
1577 1583 experimental=True,
1578 1584 )
1579 1585 coreconfigitem(
1580 1586 b'partial-merge-tools',
1581 1587 br'.*\.patterns',
1582 1588 default=dynamicdefault,
1583 1589 generic=True,
1584 1590 priority=-1,
1585 1591 experimental=True,
1586 1592 )
1587 1593 coreconfigitem(
1588 1594 b'partial-merge-tools',
1589 1595 br'.*\.executable$',
1590 1596 default=dynamicdefault,
1591 1597 generic=True,
1592 1598 priority=-1,
1593 1599 experimental=True,
1594 1600 )
1595 1601 coreconfigitem(
1596 1602 b'partial-merge-tools',
1597 1603 br'.*\.order',
1598 1604 default=0,
1599 1605 generic=True,
1600 1606 priority=-1,
1601 1607 experimental=True,
1602 1608 )
1603 1609 coreconfigitem(
1604 1610 b'partial-merge-tools',
1605 1611 br'.*\.args',
1606 1612 default=b"$local $base $other",
1607 1613 generic=True,
1608 1614 priority=-1,
1609 1615 experimental=True,
1610 1616 )
1611 1617 coreconfigitem(
1618 b'partial-merge-tools',
1619 br'.*\.disable',
1620 default=False,
1621 generic=True,
1622 priority=-1,
1623 experimental=True,
1624 )
1625 coreconfigitem(
1612 1626 b'merge-tools',
1613 1627 b'.*',
1614 1628 default=None,
1615 1629 generic=True,
1616 1630 )
1617 1631 coreconfigitem(
1618 1632 b'merge-tools',
1619 1633 br'.*\.args$',
1620 1634 default=b"$local $base $other",
1621 1635 generic=True,
1622 1636 priority=-1,
1623 1637 )
1624 1638 coreconfigitem(
1625 1639 b'merge-tools',
1626 1640 br'.*\.binary$',
1627 1641 default=False,
1628 1642 generic=True,
1629 1643 priority=-1,
1630 1644 )
1631 1645 coreconfigitem(
1632 1646 b'merge-tools',
1633 1647 br'.*\.check$',
1634 1648 default=list,
1635 1649 generic=True,
1636 1650 priority=-1,
1637 1651 )
1638 1652 coreconfigitem(
1639 1653 b'merge-tools',
1640 1654 br'.*\.checkchanged$',
1641 1655 default=False,
1642 1656 generic=True,
1643 1657 priority=-1,
1644 1658 )
1645 1659 coreconfigitem(
1646 1660 b'merge-tools',
1647 1661 br'.*\.executable$',
1648 1662 default=dynamicdefault,
1649 1663 generic=True,
1650 1664 priority=-1,
1651 1665 )
1652 1666 coreconfigitem(
1653 1667 b'merge-tools',
1654 1668 br'.*\.fixeol$',
1655 1669 default=False,
1656 1670 generic=True,
1657 1671 priority=-1,
1658 1672 )
1659 1673 coreconfigitem(
1660 1674 b'merge-tools',
1661 1675 br'.*\.gui$',
1662 1676 default=False,
1663 1677 generic=True,
1664 1678 priority=-1,
1665 1679 )
1666 1680 coreconfigitem(
1667 1681 b'merge-tools',
1668 1682 br'.*\.mergemarkers$',
1669 1683 default=b'basic',
1670 1684 generic=True,
1671 1685 priority=-1,
1672 1686 )
1673 1687 coreconfigitem(
1674 1688 b'merge-tools',
1675 1689 br'.*\.mergemarkertemplate$',
1676 1690 default=dynamicdefault, # take from command-templates.mergemarker
1677 1691 generic=True,
1678 1692 priority=-1,
1679 1693 )
1680 1694 coreconfigitem(
1681 1695 b'merge-tools',
1682 1696 br'.*\.priority$',
1683 1697 default=0,
1684 1698 generic=True,
1685 1699 priority=-1,
1686 1700 )
1687 1701 coreconfigitem(
1688 1702 b'merge-tools',
1689 1703 br'.*\.premerge$',
1690 1704 default=dynamicdefault,
1691 1705 generic=True,
1692 1706 priority=-1,
1693 1707 )
1694 1708 coreconfigitem(
1695 1709 b'merge-tools',
1696 1710 br'.*\.symlink$',
1697 1711 default=False,
1698 1712 generic=True,
1699 1713 priority=-1,
1700 1714 )
1701 1715 coreconfigitem(
1702 1716 b'pager',
1703 1717 b'attend-.*',
1704 1718 default=dynamicdefault,
1705 1719 generic=True,
1706 1720 )
1707 1721 coreconfigitem(
1708 1722 b'pager',
1709 1723 b'ignore',
1710 1724 default=list,
1711 1725 )
1712 1726 coreconfigitem(
1713 1727 b'pager',
1714 1728 b'pager',
1715 1729 default=dynamicdefault,
1716 1730 )
1717 1731 coreconfigitem(
1718 1732 b'patch',
1719 1733 b'eol',
1720 1734 default=b'strict',
1721 1735 )
1722 1736 coreconfigitem(
1723 1737 b'patch',
1724 1738 b'fuzz',
1725 1739 default=2,
1726 1740 )
1727 1741 coreconfigitem(
1728 1742 b'paths',
1729 1743 b'default',
1730 1744 default=None,
1731 1745 )
1732 1746 coreconfigitem(
1733 1747 b'paths',
1734 1748 b'default-push',
1735 1749 default=None,
1736 1750 )
1737 1751 coreconfigitem(
1738 1752 b'paths',
1739 1753 b'.*',
1740 1754 default=None,
1741 1755 generic=True,
1742 1756 )
1743 1757 coreconfigitem(
1744 1758 b'paths',
1745 1759 b'.*:bookmarks.mode',
1746 1760 default='default',
1747 1761 generic=True,
1748 1762 )
1749 1763 coreconfigitem(
1750 1764 b'paths',
1751 1765 b'.*:multi-urls',
1752 1766 default=False,
1753 1767 generic=True,
1754 1768 )
1755 1769 coreconfigitem(
1756 1770 b'paths',
1757 1771 b'.*:pushrev',
1758 1772 default=None,
1759 1773 generic=True,
1760 1774 )
1761 1775 coreconfigitem(
1762 1776 b'paths',
1763 1777 b'.*:pushurl',
1764 1778 default=None,
1765 1779 generic=True,
1766 1780 )
1767 1781 coreconfigitem(
1768 1782 b'phases',
1769 1783 b'checksubrepos',
1770 1784 default=b'follow',
1771 1785 )
1772 1786 coreconfigitem(
1773 1787 b'phases',
1774 1788 b'new-commit',
1775 1789 default=b'draft',
1776 1790 )
1777 1791 coreconfigitem(
1778 1792 b'phases',
1779 1793 b'publish',
1780 1794 default=True,
1781 1795 )
1782 1796 coreconfigitem(
1783 1797 b'profiling',
1784 1798 b'enabled',
1785 1799 default=False,
1786 1800 )
1787 1801 coreconfigitem(
1788 1802 b'profiling',
1789 1803 b'format',
1790 1804 default=b'text',
1791 1805 )
1792 1806 coreconfigitem(
1793 1807 b'profiling',
1794 1808 b'freq',
1795 1809 default=1000,
1796 1810 )
1797 1811 coreconfigitem(
1798 1812 b'profiling',
1799 1813 b'limit',
1800 1814 default=30,
1801 1815 )
1802 1816 coreconfigitem(
1803 1817 b'profiling',
1804 1818 b'nested',
1805 1819 default=0,
1806 1820 )
1807 1821 coreconfigitem(
1808 1822 b'profiling',
1809 1823 b'output',
1810 1824 default=None,
1811 1825 )
1812 1826 coreconfigitem(
1813 1827 b'profiling',
1814 1828 b'showmax',
1815 1829 default=0.999,
1816 1830 )
1817 1831 coreconfigitem(
1818 1832 b'profiling',
1819 1833 b'showmin',
1820 1834 default=dynamicdefault,
1821 1835 )
1822 1836 coreconfigitem(
1823 1837 b'profiling',
1824 1838 b'showtime',
1825 1839 default=True,
1826 1840 )
1827 1841 coreconfigitem(
1828 1842 b'profiling',
1829 1843 b'sort',
1830 1844 default=b'inlinetime',
1831 1845 )
1832 1846 coreconfigitem(
1833 1847 b'profiling',
1834 1848 b'statformat',
1835 1849 default=b'hotpath',
1836 1850 )
1837 1851 coreconfigitem(
1838 1852 b'profiling',
1839 1853 b'time-track',
1840 1854 default=dynamicdefault,
1841 1855 )
1842 1856 coreconfigitem(
1843 1857 b'profiling',
1844 1858 b'type',
1845 1859 default=b'stat',
1846 1860 )
1847 1861 coreconfigitem(
1848 1862 b'progress',
1849 1863 b'assume-tty',
1850 1864 default=False,
1851 1865 )
1852 1866 coreconfigitem(
1853 1867 b'progress',
1854 1868 b'changedelay',
1855 1869 default=1,
1856 1870 )
1857 1871 coreconfigitem(
1858 1872 b'progress',
1859 1873 b'clear-complete',
1860 1874 default=True,
1861 1875 )
1862 1876 coreconfigitem(
1863 1877 b'progress',
1864 1878 b'debug',
1865 1879 default=False,
1866 1880 )
1867 1881 coreconfigitem(
1868 1882 b'progress',
1869 1883 b'delay',
1870 1884 default=3,
1871 1885 )
1872 1886 coreconfigitem(
1873 1887 b'progress',
1874 1888 b'disable',
1875 1889 default=False,
1876 1890 )
1877 1891 coreconfigitem(
1878 1892 b'progress',
1879 1893 b'estimateinterval',
1880 1894 default=60.0,
1881 1895 )
1882 1896 coreconfigitem(
1883 1897 b'progress',
1884 1898 b'format',
1885 1899 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1886 1900 )
1887 1901 coreconfigitem(
1888 1902 b'progress',
1889 1903 b'refresh',
1890 1904 default=0.1,
1891 1905 )
1892 1906 coreconfigitem(
1893 1907 b'progress',
1894 1908 b'width',
1895 1909 default=dynamicdefault,
1896 1910 )
1897 1911 coreconfigitem(
1898 1912 b'pull',
1899 1913 b'confirm',
1900 1914 default=False,
1901 1915 )
1902 1916 coreconfigitem(
1903 1917 b'push',
1904 1918 b'pushvars.server',
1905 1919 default=False,
1906 1920 )
1907 1921 coreconfigitem(
1908 1922 b'rewrite',
1909 1923 b'backup-bundle',
1910 1924 default=True,
1911 1925 alias=[(b'ui', b'history-editing-backup')],
1912 1926 )
1913 1927 coreconfigitem(
1914 1928 b'rewrite',
1915 1929 b'update-timestamp',
1916 1930 default=False,
1917 1931 )
1918 1932 coreconfigitem(
1919 1933 b'rewrite',
1920 1934 b'empty-successor',
1921 1935 default=b'skip',
1922 1936 experimental=True,
1923 1937 )
1924 1938 # experimental as long as format.use-dirstate-v2 is.
1925 1939 coreconfigitem(
1926 1940 b'storage',
1927 1941 b'dirstate-v2.slow-path',
1928 1942 default=b"abort",
1929 1943 experimental=True,
1930 1944 )
1931 1945 coreconfigitem(
1932 1946 b'storage',
1933 1947 b'new-repo-backend',
1934 1948 default=b'revlogv1',
1935 1949 experimental=True,
1936 1950 )
1937 1951 coreconfigitem(
1938 1952 b'storage',
1939 1953 b'revlog.optimize-delta-parent-choice',
1940 1954 default=True,
1941 1955 alias=[(b'format', b'aggressivemergedeltas')],
1942 1956 )
1943 1957 coreconfigitem(
1944 1958 b'storage',
1945 1959 b'revlog.issue6528.fix-incoming',
1946 1960 default=True,
1947 1961 )
1948 1962 # experimental as long as rust is experimental (or a C version is implemented)
1949 1963 coreconfigitem(
1950 1964 b'storage',
1951 1965 b'revlog.persistent-nodemap.mmap',
1952 1966 default=True,
1953 1967 )
1954 1968 # experimental as long as format.use-persistent-nodemap is.
1955 1969 coreconfigitem(
1956 1970 b'storage',
1957 1971 b'revlog.persistent-nodemap.slow-path',
1958 1972 default=b"abort",
1959 1973 )
1960 1974
1961 1975 coreconfigitem(
1962 1976 b'storage',
1963 1977 b'revlog.reuse-external-delta',
1964 1978 default=True,
1965 1979 )
1966 1980 coreconfigitem(
1967 1981 b'storage',
1968 1982 b'revlog.reuse-external-delta-parent',
1969 1983 default=None,
1970 1984 )
1971 1985 coreconfigitem(
1972 1986 b'storage',
1973 1987 b'revlog.zlib.level',
1974 1988 default=None,
1975 1989 )
1976 1990 coreconfigitem(
1977 1991 b'storage',
1978 1992 b'revlog.zstd.level',
1979 1993 default=None,
1980 1994 )
1981 1995 coreconfigitem(
1982 1996 b'server',
1983 1997 b'bookmarks-pushkey-compat',
1984 1998 default=True,
1985 1999 )
1986 2000 coreconfigitem(
1987 2001 b'server',
1988 2002 b'bundle1',
1989 2003 default=True,
1990 2004 )
1991 2005 coreconfigitem(
1992 2006 b'server',
1993 2007 b'bundle1gd',
1994 2008 default=None,
1995 2009 )
1996 2010 coreconfigitem(
1997 2011 b'server',
1998 2012 b'bundle1.pull',
1999 2013 default=None,
2000 2014 )
2001 2015 coreconfigitem(
2002 2016 b'server',
2003 2017 b'bundle1gd.pull',
2004 2018 default=None,
2005 2019 )
2006 2020 coreconfigitem(
2007 2021 b'server',
2008 2022 b'bundle1.push',
2009 2023 default=None,
2010 2024 )
2011 2025 coreconfigitem(
2012 2026 b'server',
2013 2027 b'bundle1gd.push',
2014 2028 default=None,
2015 2029 )
2016 2030 coreconfigitem(
2017 2031 b'server',
2018 2032 b'bundle2.stream',
2019 2033 default=True,
2020 2034 alias=[(b'experimental', b'bundle2.stream')],
2021 2035 )
2022 2036 coreconfigitem(
2023 2037 b'server',
2024 2038 b'compressionengines',
2025 2039 default=list,
2026 2040 )
2027 2041 coreconfigitem(
2028 2042 b'server',
2029 2043 b'concurrent-push-mode',
2030 2044 default=b'check-related',
2031 2045 )
2032 2046 coreconfigitem(
2033 2047 b'server',
2034 2048 b'disablefullbundle',
2035 2049 default=False,
2036 2050 )
2037 2051 coreconfigitem(
2038 2052 b'server',
2039 2053 b'maxhttpheaderlen',
2040 2054 default=1024,
2041 2055 )
2042 2056 coreconfigitem(
2043 2057 b'server',
2044 2058 b'pullbundle',
2045 2059 default=False,
2046 2060 )
2047 2061 coreconfigitem(
2048 2062 b'server',
2049 2063 b'preferuncompressed',
2050 2064 default=False,
2051 2065 )
2052 2066 coreconfigitem(
2053 2067 b'server',
2054 2068 b'streamunbundle',
2055 2069 default=False,
2056 2070 )
2057 2071 coreconfigitem(
2058 2072 b'server',
2059 2073 b'uncompressed',
2060 2074 default=True,
2061 2075 )
2062 2076 coreconfigitem(
2063 2077 b'server',
2064 2078 b'uncompressedallowsecret',
2065 2079 default=False,
2066 2080 )
2067 2081 coreconfigitem(
2068 2082 b'server',
2069 2083 b'view',
2070 2084 default=b'served',
2071 2085 )
2072 2086 coreconfigitem(
2073 2087 b'server',
2074 2088 b'validate',
2075 2089 default=False,
2076 2090 )
2077 2091 coreconfigitem(
2078 2092 b'server',
2079 2093 b'zliblevel',
2080 2094 default=-1,
2081 2095 )
2082 2096 coreconfigitem(
2083 2097 b'server',
2084 2098 b'zstdlevel',
2085 2099 default=3,
2086 2100 )
2087 2101 coreconfigitem(
2088 2102 b'share',
2089 2103 b'pool',
2090 2104 default=None,
2091 2105 )
2092 2106 coreconfigitem(
2093 2107 b'share',
2094 2108 b'poolnaming',
2095 2109 default=b'identity',
2096 2110 )
2097 2111 coreconfigitem(
2098 2112 b'share',
2099 2113 b'safe-mismatch.source-not-safe',
2100 2114 default=b'abort',
2101 2115 )
2102 2116 coreconfigitem(
2103 2117 b'share',
2104 2118 b'safe-mismatch.source-safe',
2105 2119 default=b'abort',
2106 2120 )
2107 2121 coreconfigitem(
2108 2122 b'share',
2109 2123 b'safe-mismatch.source-not-safe.warn',
2110 2124 default=True,
2111 2125 )
2112 2126 coreconfigitem(
2113 2127 b'share',
2114 2128 b'safe-mismatch.source-safe.warn',
2115 2129 default=True,
2116 2130 )
2117 2131 coreconfigitem(
2118 2132 b'shelve',
2119 2133 b'maxbackups',
2120 2134 default=10,
2121 2135 )
2122 2136 coreconfigitem(
2123 2137 b'smtp',
2124 2138 b'host',
2125 2139 default=None,
2126 2140 )
2127 2141 coreconfigitem(
2128 2142 b'smtp',
2129 2143 b'local_hostname',
2130 2144 default=None,
2131 2145 )
2132 2146 coreconfigitem(
2133 2147 b'smtp',
2134 2148 b'password',
2135 2149 default=None,
2136 2150 )
2137 2151 coreconfigitem(
2138 2152 b'smtp',
2139 2153 b'port',
2140 2154 default=dynamicdefault,
2141 2155 )
2142 2156 coreconfigitem(
2143 2157 b'smtp',
2144 2158 b'tls',
2145 2159 default=b'none',
2146 2160 )
2147 2161 coreconfigitem(
2148 2162 b'smtp',
2149 2163 b'username',
2150 2164 default=None,
2151 2165 )
2152 2166 coreconfigitem(
2153 2167 b'sparse',
2154 2168 b'missingwarning',
2155 2169 default=True,
2156 2170 experimental=True,
2157 2171 )
2158 2172 coreconfigitem(
2159 2173 b'subrepos',
2160 2174 b'allowed',
2161 2175 default=dynamicdefault, # to make backporting simpler
2162 2176 )
2163 2177 coreconfigitem(
2164 2178 b'subrepos',
2165 2179 b'hg:allowed',
2166 2180 default=dynamicdefault,
2167 2181 )
2168 2182 coreconfigitem(
2169 2183 b'subrepos',
2170 2184 b'git:allowed',
2171 2185 default=dynamicdefault,
2172 2186 )
2173 2187 coreconfigitem(
2174 2188 b'subrepos',
2175 2189 b'svn:allowed',
2176 2190 default=dynamicdefault,
2177 2191 )
2178 2192 coreconfigitem(
2179 2193 b'templates',
2180 2194 b'.*',
2181 2195 default=None,
2182 2196 generic=True,
2183 2197 )
2184 2198 coreconfigitem(
2185 2199 b'templateconfig',
2186 2200 b'.*',
2187 2201 default=dynamicdefault,
2188 2202 generic=True,
2189 2203 )
2190 2204 coreconfigitem(
2191 2205 b'trusted',
2192 2206 b'groups',
2193 2207 default=list,
2194 2208 )
2195 2209 coreconfigitem(
2196 2210 b'trusted',
2197 2211 b'users',
2198 2212 default=list,
2199 2213 )
2200 2214 coreconfigitem(
2201 2215 b'ui',
2202 2216 b'_usedassubrepo',
2203 2217 default=False,
2204 2218 )
2205 2219 coreconfigitem(
2206 2220 b'ui',
2207 2221 b'allowemptycommit',
2208 2222 default=False,
2209 2223 )
2210 2224 coreconfigitem(
2211 2225 b'ui',
2212 2226 b'archivemeta',
2213 2227 default=True,
2214 2228 )
2215 2229 coreconfigitem(
2216 2230 b'ui',
2217 2231 b'askusername',
2218 2232 default=False,
2219 2233 )
2220 2234 coreconfigitem(
2221 2235 b'ui',
2222 2236 b'available-memory',
2223 2237 default=None,
2224 2238 )
2225 2239
2226 2240 coreconfigitem(
2227 2241 b'ui',
2228 2242 b'clonebundlefallback',
2229 2243 default=False,
2230 2244 )
2231 2245 coreconfigitem(
2232 2246 b'ui',
2233 2247 b'clonebundleprefers',
2234 2248 default=list,
2235 2249 )
2236 2250 coreconfigitem(
2237 2251 b'ui',
2238 2252 b'clonebundles',
2239 2253 default=True,
2240 2254 )
2241 2255 coreconfigitem(
2242 2256 b'ui',
2243 2257 b'color',
2244 2258 default=b'auto',
2245 2259 )
2246 2260 coreconfigitem(
2247 2261 b'ui',
2248 2262 b'commitsubrepos',
2249 2263 default=False,
2250 2264 )
2251 2265 coreconfigitem(
2252 2266 b'ui',
2253 2267 b'debug',
2254 2268 default=False,
2255 2269 )
2256 2270 coreconfigitem(
2257 2271 b'ui',
2258 2272 b'debugger',
2259 2273 default=None,
2260 2274 )
2261 2275 coreconfigitem(
2262 2276 b'ui',
2263 2277 b'editor',
2264 2278 default=dynamicdefault,
2265 2279 )
2266 2280 coreconfigitem(
2267 2281 b'ui',
2268 2282 b'detailed-exit-code',
2269 2283 default=False,
2270 2284 experimental=True,
2271 2285 )
2272 2286 coreconfigitem(
2273 2287 b'ui',
2274 2288 b'fallbackencoding',
2275 2289 default=None,
2276 2290 )
2277 2291 coreconfigitem(
2278 2292 b'ui',
2279 2293 b'forcecwd',
2280 2294 default=None,
2281 2295 )
2282 2296 coreconfigitem(
2283 2297 b'ui',
2284 2298 b'forcemerge',
2285 2299 default=None,
2286 2300 )
2287 2301 coreconfigitem(
2288 2302 b'ui',
2289 2303 b'formatdebug',
2290 2304 default=False,
2291 2305 )
2292 2306 coreconfigitem(
2293 2307 b'ui',
2294 2308 b'formatjson',
2295 2309 default=False,
2296 2310 )
2297 2311 coreconfigitem(
2298 2312 b'ui',
2299 2313 b'formatted',
2300 2314 default=None,
2301 2315 )
2302 2316 coreconfigitem(
2303 2317 b'ui',
2304 2318 b'interactive',
2305 2319 default=None,
2306 2320 )
2307 2321 coreconfigitem(
2308 2322 b'ui',
2309 2323 b'interface',
2310 2324 default=None,
2311 2325 )
2312 2326 coreconfigitem(
2313 2327 b'ui',
2314 2328 b'interface.chunkselector',
2315 2329 default=None,
2316 2330 )
2317 2331 coreconfigitem(
2318 2332 b'ui',
2319 2333 b'large-file-limit',
2320 2334 default=10 * (2 ** 20),
2321 2335 )
2322 2336 coreconfigitem(
2323 2337 b'ui',
2324 2338 b'logblockedtimes',
2325 2339 default=False,
2326 2340 )
2327 2341 coreconfigitem(
2328 2342 b'ui',
2329 2343 b'merge',
2330 2344 default=None,
2331 2345 )
2332 2346 coreconfigitem(
2333 2347 b'ui',
2334 2348 b'mergemarkers',
2335 2349 default=b'basic',
2336 2350 )
2337 2351 coreconfigitem(
2338 2352 b'ui',
2339 2353 b'message-output',
2340 2354 default=b'stdio',
2341 2355 )
2342 2356 coreconfigitem(
2343 2357 b'ui',
2344 2358 b'nontty',
2345 2359 default=False,
2346 2360 )
2347 2361 coreconfigitem(
2348 2362 b'ui',
2349 2363 b'origbackuppath',
2350 2364 default=None,
2351 2365 )
2352 2366 coreconfigitem(
2353 2367 b'ui',
2354 2368 b'paginate',
2355 2369 default=True,
2356 2370 )
2357 2371 coreconfigitem(
2358 2372 b'ui',
2359 2373 b'patch',
2360 2374 default=None,
2361 2375 )
2362 2376 coreconfigitem(
2363 2377 b'ui',
2364 2378 b'portablefilenames',
2365 2379 default=b'warn',
2366 2380 )
2367 2381 coreconfigitem(
2368 2382 b'ui',
2369 2383 b'promptecho',
2370 2384 default=False,
2371 2385 )
2372 2386 coreconfigitem(
2373 2387 b'ui',
2374 2388 b'quiet',
2375 2389 default=False,
2376 2390 )
2377 2391 coreconfigitem(
2378 2392 b'ui',
2379 2393 b'quietbookmarkmove',
2380 2394 default=False,
2381 2395 )
2382 2396 coreconfigitem(
2383 2397 b'ui',
2384 2398 b'relative-paths',
2385 2399 default=b'legacy',
2386 2400 )
2387 2401 coreconfigitem(
2388 2402 b'ui',
2389 2403 b'remotecmd',
2390 2404 default=b'hg',
2391 2405 )
2392 2406 coreconfigitem(
2393 2407 b'ui',
2394 2408 b'report_untrusted',
2395 2409 default=True,
2396 2410 )
2397 2411 coreconfigitem(
2398 2412 b'ui',
2399 2413 b'rollback',
2400 2414 default=True,
2401 2415 )
2402 2416 coreconfigitem(
2403 2417 b'ui',
2404 2418 b'signal-safe-lock',
2405 2419 default=True,
2406 2420 )
2407 2421 coreconfigitem(
2408 2422 b'ui',
2409 2423 b'slash',
2410 2424 default=False,
2411 2425 )
2412 2426 coreconfigitem(
2413 2427 b'ui',
2414 2428 b'ssh',
2415 2429 default=b'ssh',
2416 2430 )
2417 2431 coreconfigitem(
2418 2432 b'ui',
2419 2433 b'ssherrorhint',
2420 2434 default=None,
2421 2435 )
2422 2436 coreconfigitem(
2423 2437 b'ui',
2424 2438 b'statuscopies',
2425 2439 default=False,
2426 2440 )
2427 2441 coreconfigitem(
2428 2442 b'ui',
2429 2443 b'strict',
2430 2444 default=False,
2431 2445 )
2432 2446 coreconfigitem(
2433 2447 b'ui',
2434 2448 b'style',
2435 2449 default=b'',
2436 2450 )
2437 2451 coreconfigitem(
2438 2452 b'ui',
2439 2453 b'supportcontact',
2440 2454 default=None,
2441 2455 )
2442 2456 coreconfigitem(
2443 2457 b'ui',
2444 2458 b'textwidth',
2445 2459 default=78,
2446 2460 )
2447 2461 coreconfigitem(
2448 2462 b'ui',
2449 2463 b'timeout',
2450 2464 default=b'600',
2451 2465 )
2452 2466 coreconfigitem(
2453 2467 b'ui',
2454 2468 b'timeout.warn',
2455 2469 default=0,
2456 2470 )
2457 2471 coreconfigitem(
2458 2472 b'ui',
2459 2473 b'timestamp-output',
2460 2474 default=False,
2461 2475 )
2462 2476 coreconfigitem(
2463 2477 b'ui',
2464 2478 b'traceback',
2465 2479 default=False,
2466 2480 )
2467 2481 coreconfigitem(
2468 2482 b'ui',
2469 2483 b'tweakdefaults',
2470 2484 default=False,
2471 2485 )
2472 2486 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2473 2487 coreconfigitem(
2474 2488 b'ui',
2475 2489 b'verbose',
2476 2490 default=False,
2477 2491 )
2478 2492 coreconfigitem(
2479 2493 b'verify',
2480 2494 b'skipflags',
2481 2495 default=None,
2482 2496 )
2483 2497 coreconfigitem(
2484 2498 b'web',
2485 2499 b'allowbz2',
2486 2500 default=False,
2487 2501 )
2488 2502 coreconfigitem(
2489 2503 b'web',
2490 2504 b'allowgz',
2491 2505 default=False,
2492 2506 )
2493 2507 coreconfigitem(
2494 2508 b'web',
2495 2509 b'allow-pull',
2496 2510 alias=[(b'web', b'allowpull')],
2497 2511 default=True,
2498 2512 )
2499 2513 coreconfigitem(
2500 2514 b'web',
2501 2515 b'allow-push',
2502 2516 alias=[(b'web', b'allow_push')],
2503 2517 default=list,
2504 2518 )
2505 2519 coreconfigitem(
2506 2520 b'web',
2507 2521 b'allowzip',
2508 2522 default=False,
2509 2523 )
2510 2524 coreconfigitem(
2511 2525 b'web',
2512 2526 b'archivesubrepos',
2513 2527 default=False,
2514 2528 )
2515 2529 coreconfigitem(
2516 2530 b'web',
2517 2531 b'cache',
2518 2532 default=True,
2519 2533 )
2520 2534 coreconfigitem(
2521 2535 b'web',
2522 2536 b'comparisoncontext',
2523 2537 default=5,
2524 2538 )
2525 2539 coreconfigitem(
2526 2540 b'web',
2527 2541 b'contact',
2528 2542 default=None,
2529 2543 )
2530 2544 coreconfigitem(
2531 2545 b'web',
2532 2546 b'deny_push',
2533 2547 default=list,
2534 2548 )
2535 2549 coreconfigitem(
2536 2550 b'web',
2537 2551 b'guessmime',
2538 2552 default=False,
2539 2553 )
2540 2554 coreconfigitem(
2541 2555 b'web',
2542 2556 b'hidden',
2543 2557 default=False,
2544 2558 )
2545 2559 coreconfigitem(
2546 2560 b'web',
2547 2561 b'labels',
2548 2562 default=list,
2549 2563 )
2550 2564 coreconfigitem(
2551 2565 b'web',
2552 2566 b'logoimg',
2553 2567 default=b'hglogo.png',
2554 2568 )
2555 2569 coreconfigitem(
2556 2570 b'web',
2557 2571 b'logourl',
2558 2572 default=b'https://mercurial-scm.org/',
2559 2573 )
2560 2574 coreconfigitem(
2561 2575 b'web',
2562 2576 b'accesslog',
2563 2577 default=b'-',
2564 2578 )
2565 2579 coreconfigitem(
2566 2580 b'web',
2567 2581 b'address',
2568 2582 default=b'',
2569 2583 )
2570 2584 coreconfigitem(
2571 2585 b'web',
2572 2586 b'allow-archive',
2573 2587 alias=[(b'web', b'allow_archive')],
2574 2588 default=list,
2575 2589 )
2576 2590 coreconfigitem(
2577 2591 b'web',
2578 2592 b'allow_read',
2579 2593 default=list,
2580 2594 )
2581 2595 coreconfigitem(
2582 2596 b'web',
2583 2597 b'baseurl',
2584 2598 default=None,
2585 2599 )
2586 2600 coreconfigitem(
2587 2601 b'web',
2588 2602 b'cacerts',
2589 2603 default=None,
2590 2604 )
2591 2605 coreconfigitem(
2592 2606 b'web',
2593 2607 b'certificate',
2594 2608 default=None,
2595 2609 )
2596 2610 coreconfigitem(
2597 2611 b'web',
2598 2612 b'collapse',
2599 2613 default=False,
2600 2614 )
2601 2615 coreconfigitem(
2602 2616 b'web',
2603 2617 b'csp',
2604 2618 default=None,
2605 2619 )
2606 2620 coreconfigitem(
2607 2621 b'web',
2608 2622 b'deny_read',
2609 2623 default=list,
2610 2624 )
2611 2625 coreconfigitem(
2612 2626 b'web',
2613 2627 b'descend',
2614 2628 default=True,
2615 2629 )
2616 2630 coreconfigitem(
2617 2631 b'web',
2618 2632 b'description',
2619 2633 default=b"",
2620 2634 )
2621 2635 coreconfigitem(
2622 2636 b'web',
2623 2637 b'encoding',
2624 2638 default=lambda: encoding.encoding,
2625 2639 )
2626 2640 coreconfigitem(
2627 2641 b'web',
2628 2642 b'errorlog',
2629 2643 default=b'-',
2630 2644 )
2631 2645 coreconfigitem(
2632 2646 b'web',
2633 2647 b'ipv6',
2634 2648 default=False,
2635 2649 )
2636 2650 coreconfigitem(
2637 2651 b'web',
2638 2652 b'maxchanges',
2639 2653 default=10,
2640 2654 )
2641 2655 coreconfigitem(
2642 2656 b'web',
2643 2657 b'maxfiles',
2644 2658 default=10,
2645 2659 )
2646 2660 coreconfigitem(
2647 2661 b'web',
2648 2662 b'maxshortchanges',
2649 2663 default=60,
2650 2664 )
2651 2665 coreconfigitem(
2652 2666 b'web',
2653 2667 b'motd',
2654 2668 default=b'',
2655 2669 )
2656 2670 coreconfigitem(
2657 2671 b'web',
2658 2672 b'name',
2659 2673 default=dynamicdefault,
2660 2674 )
2661 2675 coreconfigitem(
2662 2676 b'web',
2663 2677 b'port',
2664 2678 default=8000,
2665 2679 )
2666 2680 coreconfigitem(
2667 2681 b'web',
2668 2682 b'prefix',
2669 2683 default=b'',
2670 2684 )
2671 2685 coreconfigitem(
2672 2686 b'web',
2673 2687 b'push_ssl',
2674 2688 default=True,
2675 2689 )
2676 2690 coreconfigitem(
2677 2691 b'web',
2678 2692 b'refreshinterval',
2679 2693 default=20,
2680 2694 )
2681 2695 coreconfigitem(
2682 2696 b'web',
2683 2697 b'server-header',
2684 2698 default=None,
2685 2699 )
2686 2700 coreconfigitem(
2687 2701 b'web',
2688 2702 b'static',
2689 2703 default=None,
2690 2704 )
2691 2705 coreconfigitem(
2692 2706 b'web',
2693 2707 b'staticurl',
2694 2708 default=None,
2695 2709 )
2696 2710 coreconfigitem(
2697 2711 b'web',
2698 2712 b'stripes',
2699 2713 default=1,
2700 2714 )
2701 2715 coreconfigitem(
2702 2716 b'web',
2703 2717 b'style',
2704 2718 default=b'paper',
2705 2719 )
2706 2720 coreconfigitem(
2707 2721 b'web',
2708 2722 b'templates',
2709 2723 default=None,
2710 2724 )
2711 2725 coreconfigitem(
2712 2726 b'web',
2713 2727 b'view',
2714 2728 default=b'served',
2715 2729 experimental=True,
2716 2730 )
2717 2731 coreconfigitem(
2718 2732 b'worker',
2719 2733 b'backgroundclose',
2720 2734 default=dynamicdefault,
2721 2735 )
2722 2736 # Windows defaults to a limit of 512 open files. A buffer of 128
2723 2737 # should give us enough headway.
2724 2738 coreconfigitem(
2725 2739 b'worker',
2726 2740 b'backgroundclosemaxqueue',
2727 2741 default=384,
2728 2742 )
2729 2743 coreconfigitem(
2730 2744 b'worker',
2731 2745 b'backgroundcloseminfilecount',
2732 2746 default=2048,
2733 2747 )
2734 2748 coreconfigitem(
2735 2749 b'worker',
2736 2750 b'backgroundclosethreadcount',
2737 2751 default=4,
2738 2752 )
2739 2753 coreconfigitem(
2740 2754 b'worker',
2741 2755 b'enabled',
2742 2756 default=True,
2743 2757 )
2744 2758 coreconfigitem(
2745 2759 b'worker',
2746 2760 b'numcpus',
2747 2761 default=None,
2748 2762 )
2749 2763
2750 2764 # Rebase related configuration moved to core because other extension are doing
2751 2765 # strange things. For example, shelve import the extensions to reuse some bit
2752 2766 # without formally loading it.
2753 2767 coreconfigitem(
2754 2768 b'commands',
2755 2769 b'rebase.requiredest',
2756 2770 default=False,
2757 2771 )
2758 2772 coreconfigitem(
2759 2773 b'experimental',
2760 2774 b'rebaseskipobsolete',
2761 2775 default=True,
2762 2776 )
2763 2777 coreconfigitem(
2764 2778 b'rebase',
2765 2779 b'singletransaction',
2766 2780 default=False,
2767 2781 )
2768 2782 coreconfigitem(
2769 2783 b'rebase',
2770 2784 b'experimental.inmemory',
2771 2785 default=False,
2772 2786 )
@@ -1,1299 +1,1303 b''
1 1 # filemerge.py - file-level merge handling for Mercurial
2 2 #
3 3 # Copyright 2006, 2007, 2008 Olivia Mackall <olivia@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
9 9 import contextlib
10 10 import os
11 11 import re
12 12 import shutil
13 13
14 14 from .i18n import _
15 15 from .node import (
16 16 hex,
17 17 short,
18 18 )
19 19 from .pycompat import (
20 20 getattr,
21 21 )
22 22
23 23 from . import (
24 24 encoding,
25 25 error,
26 26 formatter,
27 27 match,
28 28 pycompat,
29 29 registrar,
30 30 scmutil,
31 31 simplemerge,
32 32 tagmerge,
33 33 templatekw,
34 34 templater,
35 35 templateutil,
36 36 util,
37 37 )
38 38
39 39 from .utils import (
40 40 procutil,
41 41 stringutil,
42 42 )
43 43
44 44
45 45 def _toolstr(ui, tool, part, *args):
46 46 return ui.config(b"merge-tools", tool + b"." + part, *args)
47 47
48 48
49 49 def _toolbool(ui, tool, part, *args):
50 50 return ui.configbool(b"merge-tools", tool + b"." + part, *args)
51 51
52 52
53 53 def _toollist(ui, tool, part):
54 54 return ui.configlist(b"merge-tools", tool + b"." + part)
55 55
56 56
57 57 internals = {}
58 58 # Merge tools to document.
59 59 internalsdoc = {}
60 60
61 61 internaltool = registrar.internalmerge()
62 62
63 63 # internal tool merge types
64 64 nomerge = internaltool.nomerge
65 65 mergeonly = internaltool.mergeonly # just the full merge, no premerge
66 66 fullmerge = internaltool.fullmerge # both premerge and merge
67 67
68 68 # IMPORTANT: keep the last line of this prompt very short ("What do you want to
69 69 # do?") because of issue6158, ideally to <40 English characters (to allow other
70 70 # languages that may take more columns to still have a chance to fit in an
71 71 # 80-column screen).
72 72 _localchangedotherdeletedmsg = _(
73 73 b"file '%(fd)s' was deleted in other%(o)s but was modified in local%(l)s.\n"
74 74 b"You can use (c)hanged version, (d)elete, or leave (u)nresolved.\n"
75 75 b"What do you want to do?"
76 76 b"$$ &Changed $$ &Delete $$ &Unresolved"
77 77 )
78 78
79 79 _otherchangedlocaldeletedmsg = _(
80 80 b"file '%(fd)s' was deleted in local%(l)s but was modified in other%(o)s.\n"
81 81 b"You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.\n"
82 82 b"What do you want to do?"
83 83 b"$$ &Changed $$ &Deleted $$ &Unresolved"
84 84 )
85 85
86 86
87 87 class absentfilectx:
88 88 """Represents a file that's ostensibly in a context but is actually not
89 89 present in it.
90 90
91 91 This is here because it's very specific to the filemerge code for now --
92 92 other code is likely going to break with the values this returns."""
93 93
94 94 def __init__(self, ctx, f):
95 95 self._ctx = ctx
96 96 self._f = f
97 97
98 98 def __bytes__(self):
99 99 return b'absent file %s@%s' % (self._f, self._ctx)
100 100
101 101 def path(self):
102 102 return self._f
103 103
104 104 def size(self):
105 105 return None
106 106
107 107 def data(self):
108 108 return None
109 109
110 110 def filenode(self):
111 111 return self._ctx.repo().nullid
112 112
113 113 _customcmp = True
114 114
115 115 def cmp(self, fctx):
116 116 """compare with other file context
117 117
118 118 returns True if different from fctx.
119 119 """
120 120 return not (
121 121 fctx.isabsent()
122 122 and fctx.changectx() == self.changectx()
123 123 and fctx.path() == self.path()
124 124 )
125 125
126 126 def flags(self):
127 127 return b''
128 128
129 129 def changectx(self):
130 130 return self._ctx
131 131
132 132 def isbinary(self):
133 133 return False
134 134
135 135 def isabsent(self):
136 136 return True
137 137
138 138
139 139 def _findtool(ui, tool):
140 140 if tool in internals:
141 141 return tool
142 142 cmd = _toolstr(ui, tool, b"executable", tool)
143 143 if cmd.startswith(b'python:'):
144 144 return cmd
145 145 return findexternaltool(ui, tool)
146 146
147 147
148 148 def _quotetoolpath(cmd):
149 149 if cmd.startswith(b'python:'):
150 150 return cmd
151 151 return procutil.shellquote(cmd)
152 152
153 153
154 154 def findexternaltool(ui, tool):
155 155 for kn in (b"regkey", b"regkeyalt"):
156 156 k = _toolstr(ui, tool, kn)
157 157 if not k:
158 158 continue
159 159 p = util.lookupreg(k, _toolstr(ui, tool, b"regname"))
160 160 if p:
161 161 p = procutil.findexe(p + _toolstr(ui, tool, b"regappend", b""))
162 162 if p:
163 163 return p
164 164 exe = _toolstr(ui, tool, b"executable", tool)
165 165 return procutil.findexe(util.expandpath(exe))
166 166
167 167
168 168 def _picktool(repo, ui, path, binary, symlink, changedelete):
169 169 strictcheck = ui.configbool(b'merge', b'strict-capability-check')
170 170
171 171 def hascapability(tool, capability, strict=False):
172 172 if tool in internals:
173 173 return strict and internals[tool].capabilities.get(capability)
174 174 return _toolbool(ui, tool, capability)
175 175
176 176 def supportscd(tool):
177 177 return tool in internals and internals[tool].mergetype == nomerge
178 178
179 179 def check(tool, pat, symlink, binary, changedelete):
180 180 tmsg = tool
181 181 if pat:
182 182 tmsg = _(b"%s (for pattern %s)") % (tool, pat)
183 183 if not _findtool(ui, tool):
184 184 if pat: # explicitly requested tool deserves a warning
185 185 ui.warn(_(b"couldn't find merge tool %s\n") % tmsg)
186 186 else: # configured but non-existing tools are more silent
187 187 ui.note(_(b"couldn't find merge tool %s\n") % tmsg)
188 188 elif symlink and not hascapability(tool, b"symlink", strictcheck):
189 189 ui.warn(_(b"tool %s can't handle symlinks\n") % tmsg)
190 190 elif binary and not hascapability(tool, b"binary", strictcheck):
191 191 ui.warn(_(b"tool %s can't handle binary\n") % tmsg)
192 192 elif changedelete and not supportscd(tool):
193 193 # the nomerge tools are the only tools that support change/delete
194 194 # conflicts
195 195 pass
196 196 elif not procutil.gui() and _toolbool(ui, tool, b"gui"):
197 197 ui.warn(_(b"tool %s requires a GUI\n") % tmsg)
198 198 else:
199 199 return True
200 200 return False
201 201
202 202 # internal config: ui.forcemerge
203 203 # forcemerge comes from command line arguments, highest priority
204 204 force = ui.config(b'ui', b'forcemerge')
205 205 if force:
206 206 toolpath = _findtool(ui, force)
207 207 if changedelete and not supportscd(toolpath):
208 208 return b":prompt", None
209 209 else:
210 210 if toolpath:
211 211 return (force, _quotetoolpath(toolpath))
212 212 else:
213 213 # mimic HGMERGE if given tool not found
214 214 return (force, force)
215 215
216 216 # HGMERGE takes next precedence
217 217 hgmerge = encoding.environ.get(b"HGMERGE")
218 218 if hgmerge:
219 219 if changedelete and not supportscd(hgmerge):
220 220 return b":prompt", None
221 221 else:
222 222 return (hgmerge, hgmerge)
223 223
224 224 # then patterns
225 225
226 226 # whether binary capability should be checked strictly
227 227 binarycap = binary and strictcheck
228 228
229 229 for pat, tool in ui.configitems(b"merge-patterns"):
230 230 mf = match.match(repo.root, b'', [pat])
231 231 if mf(path) and check(tool, pat, symlink, binarycap, changedelete):
232 232 if binary and not hascapability(tool, b"binary", strict=True):
233 233 ui.warn(
234 234 _(
235 235 b"warning: check merge-patterns configurations,"
236 236 b" if %r for binary file %r is unintentional\n"
237 237 b"(see 'hg help merge-tools'"
238 238 b" for binary files capability)\n"
239 239 )
240 240 % (pycompat.bytestr(tool), pycompat.bytestr(path))
241 241 )
242 242 toolpath = _findtool(ui, tool)
243 243 return (tool, _quotetoolpath(toolpath))
244 244
245 245 # then merge tools
246 246 tools = {}
247 247 disabled = set()
248 248 for k, v in ui.configitems(b"merge-tools"):
249 249 t = k.split(b'.')[0]
250 250 if t not in tools:
251 251 tools[t] = int(_toolstr(ui, t, b"priority"))
252 252 if _toolbool(ui, t, b"disabled"):
253 253 disabled.add(t)
254 254 names = tools.keys()
255 255 tools = sorted(
256 256 [(-p, tool) for tool, p in tools.items() if tool not in disabled]
257 257 )
258 258 uimerge = ui.config(b"ui", b"merge")
259 259 if uimerge:
260 260 # external tools defined in uimerge won't be able to handle
261 261 # change/delete conflicts
262 262 if check(uimerge, path, symlink, binary, changedelete):
263 263 if uimerge not in names and not changedelete:
264 264 return (uimerge, uimerge)
265 265 tools.insert(0, (None, uimerge)) # highest priority
266 266 tools.append((None, b"hgmerge")) # the old default, if found
267 267 for p, t in tools:
268 268 if check(t, None, symlink, binary, changedelete):
269 269 toolpath = _findtool(ui, t)
270 270 return (t, _quotetoolpath(toolpath))
271 271
272 272 # internal merge or prompt as last resort
273 273 if symlink or binary or changedelete:
274 274 if not changedelete and len(tools):
275 275 # any tool is rejected by capability for symlink or binary
276 276 ui.warn(_(b"no tool found to merge %s\n") % path)
277 277 return b":prompt", None
278 278 return b":merge", None
279 279
280 280
281 281 def _eoltype(data):
282 282 """Guess the EOL type of a file"""
283 283 if b'\0' in data: # binary
284 284 return None
285 285 if b'\r\n' in data: # Windows
286 286 return b'\r\n'
287 287 if b'\r' in data: # Old Mac
288 288 return b'\r'
289 289 if b'\n' in data: # UNIX
290 290 return b'\n'
291 291 return None # unknown
292 292
293 293
294 294 def _matcheol(file, backup):
295 295 """Convert EOL markers in a file to match origfile"""
296 296 tostyle = _eoltype(backup.data()) # No repo.wread filters?
297 297 if tostyle:
298 298 data = util.readfile(file)
299 299 style = _eoltype(data)
300 300 if style:
301 301 newdata = data.replace(style, tostyle)
302 302 if newdata != data:
303 303 util.writefile(file, newdata)
304 304
305 305
306 306 @internaltool(b'prompt', nomerge)
307 307 def _iprompt(repo, mynode, local, other, base, toolconf):
308 308 """Asks the user which of the local `p1()` or the other `p2()` version to
309 309 keep as the merged version."""
310 310 ui = repo.ui
311 311 fd = local.fctx.path()
312 312 uipathfn = scmutil.getuipathfn(repo)
313 313
314 314 # Avoid prompting during an in-memory merge since it doesn't support merge
315 315 # conflicts.
316 316 if local.fctx.changectx().isinmemory():
317 317 raise error.InMemoryMergeConflictsError(
318 318 b'in-memory merge does not support file conflicts'
319 319 )
320 320
321 321 prompts = partextras([local.label, other.label])
322 322 prompts[b'fd'] = uipathfn(fd)
323 323 try:
324 324 if other.fctx.isabsent():
325 325 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2)
326 326 choice = [b'local', b'other', b'unresolved'][index]
327 327 elif local.fctx.isabsent():
328 328 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2)
329 329 choice = [b'other', b'local', b'unresolved'][index]
330 330 else:
331 331 # IMPORTANT: keep the last line of this prompt ("What do you want to
332 332 # do?") very short, see comment next to _localchangedotherdeletedmsg
333 333 # at the top of the file for details.
334 334 index = ui.promptchoice(
335 335 _(
336 336 b"file '%(fd)s' needs to be resolved.\n"
337 337 b"You can keep (l)ocal%(l)s, take (o)ther%(o)s, or leave "
338 338 b"(u)nresolved.\n"
339 339 b"What do you want to do?"
340 340 b"$$ &Local $$ &Other $$ &Unresolved"
341 341 )
342 342 % prompts,
343 343 2,
344 344 )
345 345 choice = [b'local', b'other', b'unresolved'][index]
346 346
347 347 if choice == b'other':
348 348 return _iother(repo, mynode, local, other, base, toolconf)
349 349 elif choice == b'local':
350 350 return _ilocal(repo, mynode, local, other, base, toolconf)
351 351 elif choice == b'unresolved':
352 352 return _ifail(repo, mynode, local, other, base, toolconf)
353 353 except error.ResponseExpected:
354 354 ui.write(b"\n")
355 355 return _ifail(repo, mynode, local, other, base, toolconf)
356 356
357 357
358 358 @internaltool(b'local', nomerge)
359 359 def _ilocal(repo, mynode, local, other, base, toolconf):
360 360 """Uses the local `p1()` version of files as the merged version."""
361 361 return 0, local.fctx.isabsent()
362 362
363 363
364 364 @internaltool(b'other', nomerge)
365 365 def _iother(repo, mynode, local, other, base, toolconf):
366 366 """Uses the other `p2()` version of files as the merged version."""
367 367 if other.fctx.isabsent():
368 368 # local changed, remote deleted -- 'deleted' picked
369 369 _underlyingfctxifabsent(local.fctx).remove()
370 370 deleted = True
371 371 else:
372 372 _underlyingfctxifabsent(local.fctx).write(
373 373 other.fctx.data(), other.fctx.flags()
374 374 )
375 375 deleted = False
376 376 return 0, deleted
377 377
378 378
379 379 @internaltool(b'fail', nomerge)
380 380 def _ifail(repo, mynode, local, other, base, toolconf):
381 381 """
382 382 Rather than attempting to merge files that were modified on both
383 383 branches, it marks them as unresolved. The resolve command must be
384 384 used to resolve these conflicts."""
385 385 # for change/delete conflicts write out the changed version, then fail
386 386 if local.fctx.isabsent():
387 387 _underlyingfctxifabsent(local.fctx).write(
388 388 other.fctx.data(), other.fctx.flags()
389 389 )
390 390 return 1, False
391 391
392 392
393 393 def _underlyingfctxifabsent(filectx):
394 394 """Sometimes when resolving, our fcd is actually an absentfilectx, but
395 395 we want to write to it (to do the resolve). This helper returns the
396 396 underyling workingfilectx in that case.
397 397 """
398 398 if filectx.isabsent():
399 399 return filectx.changectx()[filectx.path()]
400 400 else:
401 401 return filectx
402 402
403 403
404 404 def _verifytext(input, ui):
405 405 """verifies that text is non-binary"""
406 406 if stringutil.binary(input.text()):
407 407 msg = _(b"%s looks like a binary file.") % input.fctx.path()
408 408 ui.warn(_(b'warning: %s\n') % msg)
409 409 raise error.Abort(msg)
410 410
411 411
412 412 def _premerge(repo, local, other, base, toolconf):
413 413 tool, toolpath, binary, symlink, scriptfn = toolconf
414 414 if symlink or local.fctx.isabsent() or other.fctx.isabsent():
415 415 return 1
416 416
417 417 ui = repo.ui
418 418
419 419 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff']
420 420
421 421 # do we attempt to simplemerge first?
422 422 try:
423 423 premerge = _toolbool(ui, tool, b"premerge", not binary)
424 424 except error.ConfigError:
425 425 premerge = _toolstr(ui, tool, b"premerge", b"").lower()
426 426 if premerge not in validkeep:
427 427 _valid = b', '.join([b"'" + v + b"'" for v in validkeep])
428 428 raise error.ConfigError(
429 429 _(b"%s.premerge not valid ('%s' is neither boolean nor %s)")
430 430 % (tool, premerge, _valid)
431 431 )
432 432
433 433 if premerge:
434 434 mode = b'merge'
435 435 if premerge == b'keep-mergediff':
436 436 mode = b'mergediff'
437 437 elif premerge == b'keep-merge3':
438 438 mode = b'merge3'
439 439 if any(
440 440 stringutil.binary(input.text()) for input in (local, base, other)
441 441 ):
442 442 return 1 # continue merging
443 443 merged_text, conflicts = simplemerge.simplemerge(
444 444 local, base, other, mode=mode
445 445 )
446 446 if not conflicts or premerge in validkeep:
447 447 # fcd.flags() already has the merged flags (done in
448 448 # mergestate.resolve())
449 449 local.fctx.write(merged_text, local.fctx.flags())
450 450 if not conflicts:
451 451 ui.debug(b" premerge successful\n")
452 452 return 0
453 453 return 1 # continue merging
454 454
455 455
456 456 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf):
457 457 tool, toolpath, binary, symlink, scriptfn = toolconf
458 458 uipathfn = scmutil.getuipathfn(repo)
459 459 if symlink:
460 460 repo.ui.warn(
461 461 _(b'warning: internal %s cannot merge symlinks for %s\n')
462 462 % (tool, uipathfn(fcd.path()))
463 463 )
464 464 return False
465 465 if fcd.isabsent() or fco.isabsent():
466 466 repo.ui.warn(
467 467 _(
468 468 b'warning: internal %s cannot merge change/delete '
469 469 b'conflict for %s\n'
470 470 )
471 471 % (tool, uipathfn(fcd.path()))
472 472 )
473 473 return False
474 474 return True
475 475
476 476
477 477 def _merge(repo, local, other, base, mode):
478 478 """
479 479 Uses the internal non-interactive simple merge algorithm for merging
480 480 files. It will fail if there are any conflicts and leave markers in
481 481 the partially merged file. Markers will have two sections, one for each side
482 482 of merge, unless mode equals 'union' which suppresses the markers."""
483 483 ui = repo.ui
484 484
485 485 try:
486 486 _verifytext(local, ui)
487 487 _verifytext(base, ui)
488 488 _verifytext(other, ui)
489 489 except error.Abort:
490 490 return True, True, False
491 491 else:
492 492 merged_text, conflicts = simplemerge.simplemerge(
493 493 local, base, other, mode=mode
494 494 )
495 495 # fcd.flags() already has the merged flags (done in
496 496 # mergestate.resolve())
497 497 local.fctx.write(merged_text, local.fctx.flags())
498 498 return True, conflicts, False
499 499
500 500
501 501 @internaltool(
502 502 b'union',
503 503 fullmerge,
504 504 _(
505 505 b"warning: conflicts while merging %s! "
506 506 b"(edit, then use 'hg resolve --mark')\n"
507 507 ),
508 508 precheck=_mergecheck,
509 509 )
510 510 def _iunion(repo, mynode, local, other, base, toolconf, backup):
511 511 """
512 512 Uses the internal non-interactive simple merge algorithm for merging
513 513 files. It will use both left and right sides for conflict regions.
514 514 No markers are inserted."""
515 515 return _merge(repo, local, other, base, b'union')
516 516
517 517
518 518 @internaltool(
519 519 b'merge',
520 520 fullmerge,
521 521 _(
522 522 b"warning: conflicts while merging %s! "
523 523 b"(edit, then use 'hg resolve --mark')\n"
524 524 ),
525 525 precheck=_mergecheck,
526 526 )
527 527 def _imerge(repo, mynode, local, other, base, toolconf, backup):
528 528 """
529 529 Uses the internal non-interactive simple merge algorithm for merging
530 530 files. It will fail if there are any conflicts and leave markers in
531 531 the partially merged file. Markers will have two sections, one for each side
532 532 of merge."""
533 533 return _merge(repo, local, other, base, b'merge')
534 534
535 535
536 536 @internaltool(
537 537 b'merge3',
538 538 fullmerge,
539 539 _(
540 540 b"warning: conflicts while merging %s! "
541 541 b"(edit, then use 'hg resolve --mark')\n"
542 542 ),
543 543 precheck=_mergecheck,
544 544 )
545 545 def _imerge3(repo, mynode, local, other, base, toolconf, backup):
546 546 """
547 547 Uses the internal non-interactive simple merge algorithm for merging
548 548 files. It will fail if there are any conflicts and leave markers in
549 549 the partially merged file. Marker will have three sections, one from each
550 550 side of the merge and one for the base content."""
551 551 return _merge(repo, local, other, base, b'merge3')
552 552
553 553
554 554 @internaltool(
555 555 b'merge3-lie-about-conflicts',
556 556 fullmerge,
557 557 b'',
558 558 precheck=_mergecheck,
559 559 )
560 560 def _imerge3alwaysgood(*args, **kwargs):
561 561 # Like merge3, but record conflicts as resolved with markers in place.
562 562 #
563 563 # This is used for `diff.merge` to show the differences between
564 564 # the auto-merge state and the committed merge state. It may be
565 565 # useful for other things.
566 566 b1, junk, b2 = _imerge3(*args, **kwargs)
567 567 # TODO is this right? I'm not sure what these return values mean,
568 568 # but as far as I can tell this will indicate to callers tha the
569 569 # merge succeeded.
570 570 return b1, False, b2
571 571
572 572
573 573 @internaltool(
574 574 b'mergediff',
575 575 fullmerge,
576 576 _(
577 577 b"warning: conflicts while merging %s! "
578 578 b"(edit, then use 'hg resolve --mark')\n"
579 579 ),
580 580 precheck=_mergecheck,
581 581 )
582 582 def _imerge_diff(repo, mynode, local, other, base, toolconf, backup):
583 583 """
584 584 Uses the internal non-interactive simple merge algorithm for merging
585 585 files. It will fail if there are any conflicts and leave markers in
586 586 the partially merged file. The marker will have two sections, one with the
587 587 content from one side of the merge, and one with a diff from the base
588 588 content to the content on the other side. (experimental)"""
589 589 return _merge(repo, local, other, base, b'mergediff')
590 590
591 591
592 592 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck)
593 593 def _imergelocal(repo, mynode, local, other, base, toolconf, backup):
594 594 """
595 595 Like :merge, but resolve all conflicts non-interactively in favor
596 596 of the local `p1()` changes."""
597 597 return _merge(repo, local, other, base, b'local')
598 598
599 599
600 600 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck)
601 601 def _imergeother(repo, mynode, local, other, base, toolconf, backup):
602 602 """
603 603 Like :merge, but resolve all conflicts non-interactively in favor
604 604 of the other `p2()` changes."""
605 605 return _merge(repo, local, other, base, b'other')
606 606
607 607
608 608 @internaltool(
609 609 b'tagmerge',
610 610 mergeonly,
611 611 _(
612 612 b"automatic tag merging of %s failed! "
613 613 b"(use 'hg resolve --tool :merge' or another merge "
614 614 b"tool of your choice)\n"
615 615 ),
616 616 )
617 617 def _itagmerge(repo, mynode, local, other, base, toolconf, backup):
618 618 """
619 619 Uses the internal tag merge algorithm (experimental).
620 620 """
621 621 success, status = tagmerge.merge(repo, local.fctx, other.fctx, base.fctx)
622 622 return success, status, False
623 623
624 624
625 625 @internaltool(b'dump', fullmerge, binary=True, symlink=True)
626 626 def _idump(repo, mynode, local, other, base, toolconf, backup):
627 627 """
628 628 Creates three versions of the files to merge, containing the
629 629 contents of local, other and base. These files can then be used to
630 630 perform a merge manually. If the file to be merged is named
631 631 ``a.txt``, these files will accordingly be named ``a.txt.local``,
632 632 ``a.txt.other`` and ``a.txt.base`` and they will be placed in the
633 633 same directory as ``a.txt``.
634 634
635 635 This implies premerge. Therefore, files aren't dumped, if premerge
636 636 runs successfully. Use :forcedump to forcibly write files out.
637 637 """
638 638 a = _workingpath(repo, local.fctx)
639 639 fd = local.fctx.path()
640 640
641 641 from . import context
642 642
643 643 if isinstance(local.fctx, context.overlayworkingfilectx):
644 644 raise error.InMemoryMergeConflictsError(
645 645 b'in-memory merge does not support the :dump tool.'
646 646 )
647 647
648 648 util.writefile(a + b".local", local.fctx.decodeddata())
649 649 repo.wwrite(fd + b".other", other.fctx.data(), other.fctx.flags())
650 650 repo.wwrite(fd + b".base", base.fctx.data(), base.fctx.flags())
651 651 return False, 1, False
652 652
653 653
654 654 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True)
655 655 def _forcedump(repo, mynode, local, other, base, toolconf, backup):
656 656 """
657 657 Creates three versions of the files as same as :dump, but omits premerge.
658 658 """
659 659 return _idump(repo, mynode, local, other, base, toolconf, backup)
660 660
661 661
662 662 def _xmergeimm(repo, mynode, local, other, base, toolconf, backup):
663 663 # In-memory merge simply raises an exception on all external merge tools,
664 664 # for now.
665 665 #
666 666 # It would be possible to run most tools with temporary files, but this
667 667 # raises the question of what to do if the user only partially resolves the
668 668 # file -- we can't leave a merge state. (Copy to somewhere in the .hg/
669 669 # directory and tell the user how to get it is my best idea, but it's
670 670 # clunky.)
671 671 raise error.InMemoryMergeConflictsError(
672 672 b'in-memory merge does not support external merge tools'
673 673 )
674 674
675 675
676 676 def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args):
677 677 tmpl = ui.config(b'command-templates', b'pre-merge-tool-output')
678 678 if not tmpl:
679 679 return
680 680
681 681 mappingdict = templateutil.mappingdict
682 682 props = {
683 683 b'ctx': fcl.changectx(),
684 684 b'node': hex(mynode),
685 685 b'path': fcl.path(),
686 686 b'local': mappingdict(
687 687 {
688 688 b'ctx': fcl.changectx(),
689 689 b'fctx': fcl,
690 690 b'node': hex(mynode),
691 691 b'name': _(b'local'),
692 692 b'islink': b'l' in fcl.flags(),
693 693 b'label': env[b'HG_MY_LABEL'],
694 694 }
695 695 ),
696 696 b'base': mappingdict(
697 697 {
698 698 b'ctx': fcb.changectx(),
699 699 b'fctx': fcb,
700 700 b'name': _(b'base'),
701 701 b'islink': b'l' in fcb.flags(),
702 702 b'label': env[b'HG_BASE_LABEL'],
703 703 }
704 704 ),
705 705 b'other': mappingdict(
706 706 {
707 707 b'ctx': fco.changectx(),
708 708 b'fctx': fco,
709 709 b'name': _(b'other'),
710 710 b'islink': b'l' in fco.flags(),
711 711 b'label': env[b'HG_OTHER_LABEL'],
712 712 }
713 713 ),
714 714 b'toolpath': toolpath,
715 715 b'toolargs': args,
716 716 }
717 717
718 718 # TODO: make all of this something that can be specified on a per-tool basis
719 719 tmpl = templater.unquotestring(tmpl)
720 720
721 721 # Not using cmdutil.rendertemplate here since it causes errors importing
722 722 # things for us to import cmdutil.
723 723 tres = formatter.templateresources(ui, repo)
724 724 t = formatter.maketemplater(
725 725 ui, tmpl, defaults=templatekw.keywords, resources=tres
726 726 )
727 727 ui.status(t.renderdefault(props))
728 728
729 729
730 730 def _xmerge(repo, mynode, local, other, base, toolconf, backup):
731 731 fcd = local.fctx
732 732 fco = other.fctx
733 733 fca = base.fctx
734 734 tool, toolpath, binary, symlink, scriptfn = toolconf
735 735 uipathfn = scmutil.getuipathfn(repo)
736 736 if fcd.isabsent() or fco.isabsent():
737 737 repo.ui.warn(
738 738 _(b'warning: %s cannot merge change/delete conflict for %s\n')
739 739 % (tool, uipathfn(fcd.path()))
740 740 )
741 741 return False, 1, None
742 742 localpath = _workingpath(repo, fcd)
743 743 args = _toolstr(repo.ui, tool, b"args")
744 744
745 745 files = [
746 746 (b"base", fca.path(), fca.decodeddata()),
747 747 (b"other", fco.path(), fco.decodeddata()),
748 748 ]
749 749 outpath = b""
750 750 if b"$output" in args:
751 751 # read input from backup, write to original
752 752 outpath = localpath
753 753 localoutputpath = backup.path()
754 754 # Remove the .orig to make syntax-highlighting more likely.
755 755 if localoutputpath.endswith(b'.orig'):
756 756 localoutputpath, ext = os.path.splitext(localoutputpath)
757 757 files.append((b"local", localoutputpath, backup.data()))
758 758
759 759 with _maketempfiles(files) as temppaths:
760 760 basepath, otherpath = temppaths[:2]
761 761 if len(temppaths) == 3:
762 762 localpath = temppaths[2]
763 763
764 764 def format_label(input):
765 765 if input.label_detail:
766 766 return b'%s: %s' % (input.label, input.label_detail)
767 767 else:
768 768 return input.label
769 769
770 770 env = {
771 771 b'HG_FILE': fcd.path(),
772 772 b'HG_MY_NODE': short(mynode),
773 773 b'HG_OTHER_NODE': short(fco.changectx().node()),
774 774 b'HG_BASE_NODE': short(fca.changectx().node()),
775 775 b'HG_MY_ISLINK': b'l' in fcd.flags(),
776 776 b'HG_OTHER_ISLINK': b'l' in fco.flags(),
777 777 b'HG_BASE_ISLINK': b'l' in fca.flags(),
778 778 b'HG_MY_LABEL': format_label(local),
779 779 b'HG_OTHER_LABEL': format_label(other),
780 780 b'HG_BASE_LABEL': format_label(base),
781 781 }
782 782 ui = repo.ui
783 783
784 784 replace = {
785 785 b'local': localpath,
786 786 b'base': basepath,
787 787 b'other': otherpath,
788 788 b'output': outpath,
789 789 b'labellocal': format_label(local),
790 790 b'labelother': format_label(other),
791 791 b'labelbase': format_label(base),
792 792 }
793 793 args = util.interpolate(
794 794 br'\$',
795 795 replace,
796 796 args,
797 797 lambda s: procutil.shellquote(util.localpath(s)),
798 798 )
799 799 if _toolbool(ui, tool, b"gui"):
800 800 repo.ui.status(
801 801 _(b'running merge tool %s for file %s\n')
802 802 % (tool, uipathfn(fcd.path()))
803 803 )
804 804 if scriptfn is None:
805 805 cmd = toolpath + b' ' + args
806 806 repo.ui.debug(b'launching merge tool: %s\n' % cmd)
807 807 _describemerge(ui, repo, mynode, fcd, fca, fco, env, toolpath, args)
808 808 r = ui.system(
809 809 cmd, cwd=repo.root, environ=env, blockedtag=b'mergetool'
810 810 )
811 811 else:
812 812 repo.ui.debug(
813 813 b'launching python merge script: %s:%s\n' % (toolpath, scriptfn)
814 814 )
815 815 r = 0
816 816 try:
817 817 # avoid cycle cmdutil->merge->filemerge->extensions->cmdutil
818 818 from . import extensions
819 819
820 820 mod = extensions.loadpath(toolpath, b'hgmerge.%s' % tool)
821 821 except Exception:
822 822 raise error.Abort(
823 823 _(b"loading python merge script failed: %s") % toolpath
824 824 )
825 825 mergefn = getattr(mod, scriptfn, None)
826 826 if mergefn is None:
827 827 raise error.Abort(
828 828 _(b"%s does not have function: %s") % (toolpath, scriptfn)
829 829 )
830 830 argslist = procutil.shellsplit(args)
831 831 # avoid cycle cmdutil->merge->filemerge->hook->extensions->cmdutil
832 832 from . import hook
833 833
834 834 ret, raised = hook.pythonhook(
835 835 ui, repo, b"merge", toolpath, mergefn, {b'args': argslist}, True
836 836 )
837 837 if raised:
838 838 r = 1
839 839 repo.ui.debug(b'merge tool returned: %d\n' % r)
840 840 return True, r, False
841 841
842 842
843 843 def _populate_label_detail(input, template):
844 844 """Applies the given template to the ctx and stores it in the input."""
845 845 ctx = input.fctx.changectx()
846 846 if ctx.node() is None:
847 847 ctx = ctx.p1()
848 848
849 849 props = {b'ctx': ctx}
850 850 templateresult = template.renderdefault(props)
851 851 input.label_detail = stringutil.firstline(templateresult) # avoid '\n'
852 852
853 853
854 854 def _populate_label_details(repo, inputs, tool=None):
855 855 """Populates the label details using the conflict marker template."""
856 856 ui = repo.ui
857 857 template = ui.config(b'command-templates', b'mergemarker')
858 858 if tool is not None:
859 859 template = _toolstr(ui, tool, b'mergemarkertemplate', template)
860 860 template = templater.unquotestring(template)
861 861 tres = formatter.templateresources(ui, repo)
862 862 tmpl = formatter.maketemplater(
863 863 ui, template, defaults=templatekw.keywords, resources=tres
864 864 )
865 865
866 866 for input in inputs:
867 867 _populate_label_detail(input, tmpl)
868 868
869 869
870 870 def partextras(labels):
871 871 """Return a dictionary of extra labels for use in prompts to the user
872 872
873 873 Intended use is in strings of the form "(l)ocal%(l)s".
874 874 """
875 875 if labels is None:
876 876 return {
877 877 b"l": b"",
878 878 b"o": b"",
879 879 }
880 880
881 881 return {
882 882 b"l": b" [%s]" % labels[0],
883 883 b"o": b" [%s]" % labels[1],
884 884 }
885 885
886 886
887 887 def _makebackup(repo, ui, fcd):
888 888 """Makes and returns a filectx-like object for ``fcd``'s backup file.
889 889
890 890 In addition to preserving the user's pre-existing modifications to `fcd`
891 891 (if any), the backup is used to undo certain premerges, confirm whether a
892 892 merge changed anything, and determine what line endings the new file should
893 893 have.
894 894
895 895 Backups only need to be written once since their content doesn't change
896 896 afterwards.
897 897 """
898 898 if fcd.isabsent():
899 899 return None
900 900 # TODO: Break this import cycle somehow. (filectx -> ctx -> fileset ->
901 901 # merge -> filemerge). (I suspect the fileset import is the weakest link)
902 902 from . import context
903 903
904 904 if isinstance(fcd, context.overlayworkingfilectx):
905 905 # If we're merging in-memory, we're free to put the backup anywhere.
906 906 fd, backup = pycompat.mkstemp(b'hg-merge-backup')
907 907 with os.fdopen(fd, 'wb') as f:
908 908 f.write(fcd.data())
909 909 else:
910 910 backup = scmutil.backuppath(ui, repo, fcd.path())
911 911 a = _workingpath(repo, fcd)
912 912 util.copyfile(a, backup)
913 913
914 914 return context.arbitraryfilectx(backup, repo=repo)
915 915
916 916
917 917 @contextlib.contextmanager
918 918 def _maketempfiles(files):
919 919 """Creates a temporary file for each (prefix, path, data) tuple in `files`,
920 920 so an external merge tool may use them.
921 921 """
922 922 tmproot = pycompat.mkdtemp(prefix=b'hgmerge-')
923 923
924 924 def maketempfrompath(prefix, path, data):
925 925 fullbase, ext = os.path.splitext(path)
926 926 pre = b"%s~%s" % (os.path.basename(fullbase), prefix)
927 927 name = os.path.join(tmproot, pre)
928 928 if ext:
929 929 name += ext
930 930 util.writefile(name, data)
931 931 return name
932 932
933 933 temp_files = []
934 934 for prefix, path, data in files:
935 935 temp_files.append(maketempfrompath(prefix, path, data))
936 936 try:
937 937 yield temp_files
938 938 finally:
939 939 shutil.rmtree(tmproot)
940 940
941 941
942 942 def filemerge(repo, wctx, mynode, orig, fcd, fco, fca, labels=None):
943 943 """perform a 3-way merge in the working directory
944 944
945 945 mynode = parent node before merge
946 946 orig = original local filename before merge
947 947 fco = other file context
948 948 fca = ancestor file context
949 949 fcd = local file context for current/destination file
950 950
951 951 Returns whether the merge is complete, the return value of the merge, and
952 952 a boolean indicating whether the file was deleted from disk."""
953 953 ui = repo.ui
954 954 fd = fcd.path()
955 955 uipathfn = scmutil.getuipathfn(repo)
956 956 fduipath = uipathfn(fd)
957 957 binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
958 958 symlink = b'l' in fcd.flags() + fco.flags()
959 959 changedelete = fcd.isabsent() or fco.isabsent()
960 960 tool, toolpath = _picktool(repo, ui, fd, binary, symlink, changedelete)
961 961 scriptfn = None
962 962 if tool in internals and tool.startswith(b'internal:'):
963 963 # normalize to new-style names (':merge' etc)
964 964 tool = tool[len(b'internal') :]
965 965 if toolpath and toolpath.startswith(b'python:'):
966 966 invalidsyntax = False
967 967 if toolpath.count(b':') >= 2:
968 968 script, scriptfn = toolpath[7:].rsplit(b':', 1)
969 969 if not scriptfn:
970 970 invalidsyntax = True
971 971 # missing :callable can lead to spliting on windows drive letter
972 972 if b'\\' in scriptfn or b'/' in scriptfn:
973 973 invalidsyntax = True
974 974 else:
975 975 invalidsyntax = True
976 976 if invalidsyntax:
977 977 raise error.Abort(_(b"invalid 'python:' syntax: %s") % toolpath)
978 978 toolpath = script
979 979 ui.debug(
980 980 b"picked tool '%s' for %s (binary %s symlink %s changedelete %s)\n"
981 981 % (
982 982 tool,
983 983 fduipath,
984 984 pycompat.bytestr(binary),
985 985 pycompat.bytestr(symlink),
986 986 pycompat.bytestr(changedelete),
987 987 )
988 988 )
989 989
990 990 if tool in internals:
991 991 func = internals[tool]
992 992 mergetype = func.mergetype
993 993 onfailure = func.onfailure
994 994 precheck = func.precheck
995 995 isexternal = False
996 996 else:
997 997 if wctx.isinmemory():
998 998 func = _xmergeimm
999 999 else:
1000 1000 func = _xmerge
1001 1001 mergetype = fullmerge
1002 1002 onfailure = _(b"merging %s failed!\n")
1003 1003 precheck = None
1004 1004 isexternal = True
1005 1005
1006 1006 toolconf = tool, toolpath, binary, symlink, scriptfn
1007 1007
1008 1008 if not labels:
1009 1009 labels = [b'local', b'other']
1010 1010 if len(labels) < 3:
1011 1011 labels.append(b'base')
1012 1012 local = simplemerge.MergeInput(fcd, labels[0])
1013 1013 other = simplemerge.MergeInput(fco, labels[1])
1014 1014 base = simplemerge.MergeInput(fca, labels[2])
1015 1015 if mergetype == nomerge:
1016 1016 return func(
1017 1017 repo,
1018 1018 mynode,
1019 1019 local,
1020 1020 other,
1021 1021 base,
1022 1022 toolconf,
1023 1023 )
1024 1024
1025 1025 if orig != fco.path():
1026 1026 ui.status(
1027 1027 _(b"merging %s and %s to %s\n")
1028 1028 % (uipathfn(orig), uipathfn(fco.path()), fduipath)
1029 1029 )
1030 1030 else:
1031 1031 ui.status(_(b"merging %s\n") % fduipath)
1032 1032
1033 1033 ui.debug(b"my %s other %s ancestor %s\n" % (fcd, fco, fca))
1034 1034
1035 1035 if precheck and not precheck(repo, mynode, fcd, fco, fca, toolconf):
1036 1036 if onfailure:
1037 1037 if wctx.isinmemory():
1038 1038 raise error.InMemoryMergeConflictsError(
1039 1039 b'in-memory merge does not support merge conflicts'
1040 1040 )
1041 1041 ui.warn(onfailure % fduipath)
1042 1042 return 1, False
1043 1043
1044 1044 backup = _makebackup(repo, ui, fcd)
1045 1045 r = 1
1046 1046 try:
1047 1047 internalmarkerstyle = ui.config(b'ui', b'mergemarkers')
1048 1048 if isexternal:
1049 1049 markerstyle = _toolstr(ui, tool, b'mergemarkers')
1050 1050 else:
1051 1051 markerstyle = internalmarkerstyle
1052 1052
1053 1053 if mergetype == fullmerge:
1054 1054 _run_partial_resolution_tools(repo, local, other, base)
1055 1055 # conflict markers generated by premerge will use 'detailed'
1056 1056 # settings if either ui.mergemarkers or the tool's mergemarkers
1057 1057 # setting is 'detailed'. This way tools can have basic labels in
1058 1058 # space-constrained areas of the UI, but still get full information
1059 1059 # in conflict markers if premerge is 'keep' or 'keep-merge3'.
1060 1060 labeltool = None
1061 1061 if markerstyle != b'basic':
1062 1062 # respect 'tool's mergemarkertemplate (which defaults to
1063 1063 # command-templates.mergemarker)
1064 1064 labeltool = tool
1065 1065 if internalmarkerstyle != b'basic' or markerstyle != b'basic':
1066 1066 _populate_label_details(
1067 1067 repo, [local, other, base], tool=labeltool
1068 1068 )
1069 1069
1070 1070 r = _premerge(
1071 1071 repo,
1072 1072 local,
1073 1073 other,
1074 1074 base,
1075 1075 toolconf,
1076 1076 )
1077 1077 # we're done if premerge was successful (r is 0)
1078 1078 if not r:
1079 1079 return r, False
1080 1080
1081 1081 # Reset to basic labels
1082 1082 local.label_detail = None
1083 1083 other.label_detail = None
1084 1084 base.label_detail = None
1085 1085
1086 1086 if markerstyle != b'basic':
1087 1087 _populate_label_details(repo, [local, other, base], tool=tool)
1088 1088
1089 1089 needcheck, r, deleted = func(
1090 1090 repo,
1091 1091 mynode,
1092 1092 local,
1093 1093 other,
1094 1094 base,
1095 1095 toolconf,
1096 1096 backup,
1097 1097 )
1098 1098
1099 1099 if needcheck:
1100 1100 r = _check(repo, r, ui, tool, fcd, backup)
1101 1101
1102 1102 if r:
1103 1103 if onfailure:
1104 1104 if wctx.isinmemory():
1105 1105 raise error.InMemoryMergeConflictsError(
1106 1106 b'in-memory merge '
1107 1107 b'does not support '
1108 1108 b'merge conflicts'
1109 1109 )
1110 1110 ui.warn(onfailure % fduipath)
1111 1111 _onfilemergefailure(ui)
1112 1112
1113 1113 return r, deleted
1114 1114 finally:
1115 1115 if not r and backup is not None:
1116 1116 backup.remove()
1117 1117
1118 1118
1119 1119 def _run_partial_resolution_tools(repo, local, other, base):
1120 1120 """Runs partial-resolution tools on the three inputs and updates them."""
1121 1121 ui = repo.ui
1122 if ui.configbool(b'merge', b'disable-partial-tools'):
1123 return
1122 1124 # Tuples of (order, name, executable path, args)
1123 1125 tools = []
1124 1126 seen = set()
1125 1127 section = b"partial-merge-tools"
1126 1128 for k, v in ui.configitems(section):
1127 1129 name = k.split(b'.')[0]
1128 1130 if name in seen:
1129 1131 continue
1130 1132 patterns = ui.configlist(section, b'%s.patterns' % name, [])
1131 1133 is_match = True
1132 1134 if patterns:
1133 1135 m = match.match(repo.root, b'', patterns)
1134 1136 is_match = m(local.fctx.path())
1135 1137 if is_match:
1138 if ui.configbool(section, b'%s.disable' % name):
1139 continue
1136 1140 order = ui.configint(section, b'%s.order' % name, 0)
1137 1141 executable = ui.config(section, b'%s.executable' % name, name)
1138 1142 args = ui.config(section, b'%s.args' % name)
1139 1143 tools.append((order, name, executable, args))
1140 1144
1141 1145 if not tools:
1142 1146 return
1143 1147 # Sort in configured order (first in tuple)
1144 1148 tools.sort()
1145 1149
1146 1150 files = [
1147 1151 (b"local", local.fctx.path(), local.text()),
1148 1152 (b"base", base.fctx.path(), base.text()),
1149 1153 (b"other", other.fctx.path(), other.text()),
1150 1154 ]
1151 1155
1152 1156 with _maketempfiles(files) as temppaths:
1153 1157 localpath, basepath, otherpath = temppaths
1154 1158
1155 1159 for order, name, executable, args in tools:
1156 1160 cmd = procutil.shellquote(executable)
1157 1161 replace = {
1158 1162 b'local': localpath,
1159 1163 b'base': basepath,
1160 1164 b'other': otherpath,
1161 1165 }
1162 1166 args = util.interpolate(
1163 1167 br'\$',
1164 1168 replace,
1165 1169 args,
1166 1170 lambda s: procutil.shellquote(util.localpath(s)),
1167 1171 )
1168 1172
1169 1173 cmd = b'%s %s' % (cmd, args)
1170 1174 r = ui.system(cmd, cwd=repo.root, blockedtag=b'partial-mergetool')
1171 1175 if r:
1172 1176 raise error.StateError(
1173 1177 b'partial merge tool %s exited with code %d' % (name, r)
1174 1178 )
1175 1179 local_text = util.readfile(localpath)
1176 1180 other_text = util.readfile(otherpath)
1177 1181 if local_text == other_text:
1178 1182 # No need to run other tools if all conflicts have been resolved
1179 1183 break
1180 1184
1181 1185 local.set_text(local_text)
1182 1186 base.set_text(util.readfile(basepath))
1183 1187 other.set_text(other_text)
1184 1188
1185 1189
1186 1190 def _haltmerge():
1187 1191 msg = _(b'merge halted after failed merge (see hg resolve)')
1188 1192 raise error.InterventionRequired(msg)
1189 1193
1190 1194
1191 1195 def _onfilemergefailure(ui):
1192 1196 action = ui.config(b'merge', b'on-failure')
1193 1197 if action == b'prompt':
1194 1198 msg = _(b'continue merge operation (yn)?$$ &Yes $$ &No')
1195 1199 if ui.promptchoice(msg, 0) == 1:
1196 1200 _haltmerge()
1197 1201 if action == b'halt':
1198 1202 _haltmerge()
1199 1203 # default action is 'continue', in which case we neither prompt nor halt
1200 1204
1201 1205
1202 1206 def hasconflictmarkers(data):
1203 1207 # Detect lines starting with a string of 7 identical characters from the
1204 1208 # subset Mercurial uses for conflict markers, followed by either the end of
1205 1209 # line or a space and some text. Note that using [<>=+|-]{7} would detect
1206 1210 # `<><><><><` as a conflict marker, which we don't want.
1207 1211 return bool(
1208 1212 re.search(
1209 1213 br"^([<>=+|-])\1{6}( .*)$",
1210 1214 data,
1211 1215 re.MULTILINE,
1212 1216 )
1213 1217 )
1214 1218
1215 1219
1216 1220 def _check(repo, r, ui, tool, fcd, backup):
1217 1221 fd = fcd.path()
1218 1222 uipathfn = scmutil.getuipathfn(repo)
1219 1223
1220 1224 if not r and (
1221 1225 _toolbool(ui, tool, b"checkconflicts")
1222 1226 or b'conflicts' in _toollist(ui, tool, b"check")
1223 1227 ):
1224 1228 if hasconflictmarkers(fcd.data()):
1225 1229 r = 1
1226 1230
1227 1231 checked = False
1228 1232 if b'prompt' in _toollist(ui, tool, b"check"):
1229 1233 checked = True
1230 1234 if ui.promptchoice(
1231 1235 _(b"was merge of '%s' successful (yn)?$$ &Yes $$ &No")
1232 1236 % uipathfn(fd),
1233 1237 1,
1234 1238 ):
1235 1239 r = 1
1236 1240
1237 1241 if (
1238 1242 not r
1239 1243 and not checked
1240 1244 and (
1241 1245 _toolbool(ui, tool, b"checkchanged")
1242 1246 or b'changed' in _toollist(ui, tool, b"check")
1243 1247 )
1244 1248 ):
1245 1249 if backup is not None and not fcd.cmp(backup):
1246 1250 if ui.promptchoice(
1247 1251 _(
1248 1252 b" output file %s appears unchanged\n"
1249 1253 b"was merge successful (yn)?"
1250 1254 b"$$ &Yes $$ &No"
1251 1255 )
1252 1256 % uipathfn(fd),
1253 1257 1,
1254 1258 ):
1255 1259 r = 1
1256 1260
1257 1261 if backup is not None and _toolbool(ui, tool, b"fixeol"):
1258 1262 _matcheol(_workingpath(repo, fcd), backup)
1259 1263
1260 1264 return r
1261 1265
1262 1266
1263 1267 def _workingpath(repo, ctx):
1264 1268 return repo.wjoin(ctx.path())
1265 1269
1266 1270
1267 1271 def loadinternalmerge(ui, extname, registrarobj):
1268 1272 """Load internal merge tool from specified registrarobj"""
1269 1273 for name, func in registrarobj._table.items():
1270 1274 fullname = b':' + name
1271 1275 internals[fullname] = func
1272 1276 internals[b'internal:' + name] = func
1273 1277 internalsdoc[fullname] = func
1274 1278
1275 1279 capabilities = sorted([k for k, v in func.capabilities.items() if v])
1276 1280 if capabilities:
1277 1281 capdesc = b" (actual capabilities: %s)" % b', '.join(
1278 1282 capabilities
1279 1283 )
1280 1284 func.__doc__ = func.__doc__ + pycompat.sysstr(b"\n\n%s" % capdesc)
1281 1285
1282 1286 # to put i18n comments into hg.pot for automatically generated texts
1283 1287
1284 1288 # i18n: "binary" and "symlink" are keywords
1285 1289 # i18n: this text is added automatically
1286 1290 _(b" (actual capabilities: binary, symlink)")
1287 1291 # i18n: "binary" is keyword
1288 1292 # i18n: this text is added automatically
1289 1293 _(b" (actual capabilities: binary)")
1290 1294 # i18n: "symlink" is keyword
1291 1295 # i18n: this text is added automatically
1292 1296 _(b" (actual capabilities: symlink)")
1293 1297
1294 1298
1295 1299 # load built-in merge tools explicitly to setup internalsdoc
1296 1300 loadinternalmerge(None, None, internaltool)
1297 1301
1298 1302 # tell hggettext to extract docstrings from these functions:
1299 1303 i18nfunctions = internals.values()
@@ -1,241 +1,292 b''
1 1 Test support for partial-resolution tools
2 2
3 3 Create a tool that resolves conflicts after line 5 by simply dropping those
4 4 lines (even if there are no conflicts there)
5 5 $ cat >> "$TESTTMP/head.sh" <<'EOF'
6 6 > #!/bin/sh
7 7 > for f in "$@"; do
8 8 > head -5 $f > tmp
9 9 > mv -f tmp $f
10 10 > done
11 11 > EOF
12 12 $ chmod +x "$TESTTMP/head.sh"
13 13 ...and another tool that keeps only the last 5 lines instead of the first 5.
14 14 $ cat >> "$TESTTMP/tail.sh" <<'EOF'
15 15 > #!/bin/sh
16 16 > for f in "$@"; do
17 17 > tail -5 $f > tmp
18 18 > mv -f tmp $f
19 19 > done
20 20 > EOF
21 21 $ chmod +x "$TESTTMP/tail.sh"
22 22
23 23 Set up both tools to run on all patterns (the default), and let the `tail` tool
24 24 run after the `head` tool, which means it will have no effect (we'll override it
25 25 to test order later)
26 26 $ cat >> "$HGRCPATH" <<EOF
27 27 > [partial-merge-tools]
28 28 > head.executable=$TESTTMP/head.sh
29 29 > tail.executable=$TESTTMP/tail.sh
30 30 > tail.order=1
31 31 > EOF
32 32
33 33 $ make_commit() {
34 34 > echo "$@" | xargs -n1 > file
35 35 > hg add file 2> /dev/null
36 36 > hg ci -m "$*"
37 37 > }
38 38
39 39
40 40 Let a partial-resolution tool resolve some conflicts and leave other conflicts
41 41 for the regular merge tool (:merge3 here)
42 42
43 43 $ hg init repo
44 44 $ cd repo
45 45 $ make_commit a b c d e f
46 46 $ make_commit a b2 c d e f2
47 47 $ hg up 0
48 48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 49 $ make_commit a b3 c d e f3
50 50 created new head
51 51 $ hg merge 1 -t :merge3
52 52 merging file
53 53 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
54 54 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
55 55 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
56 56 [1]
57 57 $ cat file
58 58 a
59 59 <<<<<<< working copy: e11a49d4b620 - test: a b3 c d e f3
60 60 b3
61 61 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
62 62 b
63 63 =======
64 64 b2
65 65 >>>>>>> merge rev: fbc096a40cc5 - test: a b2 c d e f2
66 66 c
67 67 d
68 68 e
69 69
70 70
71 71 With premerge=keep, the partial-resolution tools runs before and doesn't see
72 72 the conflict markers
73 73
74 74 $ hg up -C 2
75 75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76 $ cat >> .hg/hgrc <<EOF
77 77 > [merge-tools]
78 78 > my-local.executable = cat
79 79 > my-local.args = $local
80 80 > my-local.premerge = keep-merge3
81 81 > EOF
82 82 $ hg merge 1 -t my-local
83 83 merging file
84 84 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
85 85 (branch merge, don't forget to commit)
86 86 $ cat file
87 87 a
88 88 <<<<<<< working copy: e11a49d4b620 - test: a b3 c d e f3
89 89 b3
90 90 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
91 91 b
92 92 =======
93 93 b2
94 94 >>>>>>> merge rev: fbc096a40cc5 - test: a b2 c d e f2
95 95 c
96 96 d
97 97 e
98 98
99 99
100 100 When a partial-resolution tool resolves all conflicts, the resolution should
101 101 be recorded and the regular merge tool should not be invoked for the file.
102 102
103 103 $ hg up -C 0
104 104 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
105 105 $ make_commit a b c d e f2
106 106 created new head
107 107 $ hg up 0
108 108 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 $ make_commit a b c d e f3
110 110 created new head
111 111 $ hg merge 3 -t false
112 112 merging file
113 113 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 114 (branch merge, don't forget to commit)
115 115 $ cat file
116 116 a
117 117 b
118 118 c
119 119 d
120 120 e
121 121
122 122
123 Can disable all partial merge tools (the `head` tool would have resolved this
124 conflict it had been enabled)
125
126 $ hg up -C 4
127 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 $ hg merge 3 -t :merge3 --config merge.disable-partial-tools=yes
129 merging file
130 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
131 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
132 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
133 [1]
134 $ cat file
135 a
136 b
137 c
138 d
139 e
140 <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3
141 f3
142 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
143 f
144 =======
145 f2
146 >>>>>>> merge rev: 8c217da987be - test: a b c d e f2
147
148
149 Can disable one partial merge tool (the `head` tool would have resolved this
150 conflict it had been enabled)
151
152 $ hg up -C 4
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 $ hg merge 3 -t :merge3 --config partial-merge-tools.head.disable=yes
155 merging file
156 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
157 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
158 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
159 [1]
160 $ cat file
161 b
162 c
163 d
164 e
165 <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3
166 f3
167 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
168 f
169 =======
170 f2
171 >>>>>>> merge rev: 8c217da987be - test: a b c d e f2
172
173
123 174 Only tools whose patterns match are run. We make `head` not match here, so
124 175 only `tail` should run
125 176
126 177 $ hg up -C 4
127 178 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 179 $ hg merge 3 -t :merge3 --config partial-merge-tools.head.patterns=other
129 180 merging file
130 181 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
131 182 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
132 183 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
133 184 [1]
134 185 $ cat file
135 186 b
136 187 c
137 188 d
138 189 e
139 190 <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3
140 191 f3
141 192 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
142 193 f
143 194 =======
144 195 f2
145 196 >>>>>>> merge rev: 8c217da987be - test: a b c d e f2
146 197
147 198
148 199 If there are several matching tools, they are run in requested order. We move
149 200 `head` after `tail` in order here so it has no effect (the conflict in "f" thus
150 201 remains).
151 202
152 203 $ hg up -C 4
153 204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 205 $ hg merge 3 -t :merge3 --config partial-merge-tools.head.order=2
155 206 merging file
156 207 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
157 208 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
158 209 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
159 210 [1]
160 211 $ cat file
161 212 b
162 213 c
163 214 d
164 215 e
165 216 <<<<<<< working copy: d57edaa6e21a - test: a b c d e f3
166 217 f3
167 218 ||||||| common ancestor: 8ae8bb9cc43a - test: a b c d e f
168 219 f
169 220 =======
170 221 f2
171 222 >>>>>>> merge rev: 8c217da987be - test: a b c d e f2
172 223
173 224
174 225 When using "nomerge" tools (e.g. `:other`), the partial-resolution tools
175 226 should not be run.
176 227
177 228 $ hg up -C 4
178 229 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 230 $ hg merge 3 -t :other
180 231 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
181 232 (branch merge, don't forget to commit)
182 233 $ cat file
183 234 a
184 235 b
185 236 c
186 237 d
187 238 e
188 239 f2
189 240
190 241
191 242 If a partial-resolution tool resolved some conflict and simplemerge can
192 243 merge the rest, then the regular merge tool should not be used. Here we merge
193 244 "a b c d e3 f3" with "a b2 c d e f2". The `head` tool resolves the conflict in
194 245 "f" and the internal simplemerge merges the remaining changes in "b" and "e".
195 246
196 247 $ hg up -C 0
197 248 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
198 249 $ make_commit a b c d e3 f3
199 250 created new head
200 251 $ hg merge 1 -t false
201 252 merging file
202 253 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
203 254 (branch merge, don't forget to commit)
204 255 $ cat file
205 256 a
206 257 b2
207 258 c
208 259 d
209 260 e3
210 261
211 262 Test that arguments get passed as expected.
212 263
213 264 $ cat >> "$TESTTMP/log-args.sh" <<'EOF'
214 265 > #!/bin/sh
215 266 > echo "$@" > args.log
216 267 > EOF
217 268 $ chmod +x "$TESTTMP/log-args.sh"
218 269 $ cat >> "$HGRCPATH" <<EOF
219 270 > [partial-merge-tools]
220 271 > log-args.executable=$TESTTMP/log-args.sh
221 272 > EOF
222 273 $ hg up -C 2
223 274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 275 $ hg merge 1
225 276 merging file
226 277 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
227 278 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
228 279 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
229 280 [1]
230 281 $ cat args.log
231 282 */hgmerge-*/file~local */hgmerge-*/file~base */hgmerge-*/file~other (glob)
232 283 $ hg up -C 2
233 284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 285 $ hg merge 1 --config partial-merge-tools.log-args.args='--other $other $base --foo --local $local --also-other $other'
235 286 merging file
236 287 warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
237 288 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
238 289 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
239 290 [1]
240 291 $ cat args.log
241 292 --other */hgmerge-*/file~other */hgmerge-*/file~base --foo --local */hgmerge-*/file~local --also-other */hgmerge-*/file~other (glob)
General Comments 0
You need to be logged in to leave comments. Login now