##// END OF EJS Templates
copies: add an devel option to trace all files...
marmoute -
r47137:e948ad0d default
parent child Browse files
Show More
@@ -1,2599 +1,2605 b''
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import functools
11 11 import re
12 12
13 13 from . import (
14 14 encoding,
15 15 error,
16 16 )
17 17
18 18
19 19 def loadconfigtable(ui, extname, configtable):
20 20 """update config item known to the ui with the extension ones"""
21 21 for section, items in sorted(configtable.items()):
22 22 knownitems = ui._knownconfig.setdefault(section, itemregister())
23 23 knownkeys = set(knownitems)
24 24 newkeys = set(items)
25 25 for key in sorted(knownkeys & newkeys):
26 26 msg = b"extension '%s' overwrite config item '%s.%s'"
27 27 msg %= (extname, section, key)
28 28 ui.develwarn(msg, config=b'warn-config')
29 29
30 30 knownitems.update(items)
31 31
32 32
33 33 class configitem(object):
34 34 """represent a known config item
35 35
36 36 :section: the official config section where to find this item,
37 37 :name: the official name within the section,
38 38 :default: default value for this item,
39 39 :alias: optional list of tuples as alternatives,
40 40 :generic: this is a generic definition, match name using regular expression.
41 41 """
42 42
43 43 def __init__(
44 44 self,
45 45 section,
46 46 name,
47 47 default=None,
48 48 alias=(),
49 49 generic=False,
50 50 priority=0,
51 51 experimental=False,
52 52 ):
53 53 self.section = section
54 54 self.name = name
55 55 self.default = default
56 56 self.alias = list(alias)
57 57 self.generic = generic
58 58 self.priority = priority
59 59 self.experimental = experimental
60 60 self._re = None
61 61 if generic:
62 62 self._re = re.compile(self.name)
63 63
64 64
65 65 class itemregister(dict):
66 66 """A specialized dictionary that can handle wild-card selection"""
67 67
68 68 def __init__(self):
69 69 super(itemregister, self).__init__()
70 70 self._generics = set()
71 71
72 72 def update(self, other):
73 73 super(itemregister, self).update(other)
74 74 self._generics.update(other._generics)
75 75
76 76 def __setitem__(self, key, item):
77 77 super(itemregister, self).__setitem__(key, item)
78 78 if item.generic:
79 79 self._generics.add(item)
80 80
81 81 def get(self, key):
82 82 baseitem = super(itemregister, self).get(key)
83 83 if baseitem is not None and not baseitem.generic:
84 84 return baseitem
85 85
86 86 # search for a matching generic item
87 87 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
88 88 for item in generics:
89 89 # we use 'match' instead of 'search' to make the matching simpler
90 90 # for people unfamiliar with regular expression. Having the match
91 91 # rooted to the start of the string will produce less surprising
92 92 # result for user writing simple regex for sub-attribute.
93 93 #
94 94 # For example using "color\..*" match produces an unsurprising
95 95 # result, while using search could suddenly match apparently
96 96 # unrelated configuration that happens to contains "color."
97 97 # anywhere. This is a tradeoff where we favor requiring ".*" on
98 98 # some match to avoid the need to prefix most pattern with "^".
99 99 # The "^" seems more error prone.
100 100 if item._re.match(key):
101 101 return item
102 102
103 103 return None
104 104
105 105
106 106 coreitems = {}
107 107
108 108
109 109 def _register(configtable, *args, **kwargs):
110 110 item = configitem(*args, **kwargs)
111 111 section = configtable.setdefault(item.section, itemregister())
112 112 if item.name in section:
113 113 msg = b"duplicated config item registration for '%s.%s'"
114 114 raise error.ProgrammingError(msg % (item.section, item.name))
115 115 section[item.name] = item
116 116
117 117
118 118 # special value for case where the default is derived from other values
119 119 dynamicdefault = object()
120 120
121 121 # Registering actual config items
122 122
123 123
124 124 def getitemregister(configtable):
125 125 f = functools.partial(_register, configtable)
126 126 # export pseudo enum as configitem.*
127 127 f.dynamicdefault = dynamicdefault
128 128 return f
129 129
130 130
131 131 coreconfigitem = getitemregister(coreitems)
132 132
133 133
134 134 def _registerdiffopts(section, configprefix=b''):
135 135 coreconfigitem(
136 136 section,
137 137 configprefix + b'nodates',
138 138 default=False,
139 139 )
140 140 coreconfigitem(
141 141 section,
142 142 configprefix + b'showfunc',
143 143 default=False,
144 144 )
145 145 coreconfigitem(
146 146 section,
147 147 configprefix + b'unified',
148 148 default=None,
149 149 )
150 150 coreconfigitem(
151 151 section,
152 152 configprefix + b'git',
153 153 default=False,
154 154 )
155 155 coreconfigitem(
156 156 section,
157 157 configprefix + b'ignorews',
158 158 default=False,
159 159 )
160 160 coreconfigitem(
161 161 section,
162 162 configprefix + b'ignorewsamount',
163 163 default=False,
164 164 )
165 165 coreconfigitem(
166 166 section,
167 167 configprefix + b'ignoreblanklines',
168 168 default=False,
169 169 )
170 170 coreconfigitem(
171 171 section,
172 172 configprefix + b'ignorewseol',
173 173 default=False,
174 174 )
175 175 coreconfigitem(
176 176 section,
177 177 configprefix + b'nobinary',
178 178 default=False,
179 179 )
180 180 coreconfigitem(
181 181 section,
182 182 configprefix + b'noprefix',
183 183 default=False,
184 184 )
185 185 coreconfigitem(
186 186 section,
187 187 configprefix + b'word-diff',
188 188 default=False,
189 189 )
190 190
191 191
192 192 coreconfigitem(
193 193 b'alias',
194 194 b'.*',
195 195 default=dynamicdefault,
196 196 generic=True,
197 197 )
198 198 coreconfigitem(
199 199 b'auth',
200 200 b'cookiefile',
201 201 default=None,
202 202 )
203 203 _registerdiffopts(section=b'annotate')
204 204 # bookmarks.pushing: internal hack for discovery
205 205 coreconfigitem(
206 206 b'bookmarks',
207 207 b'pushing',
208 208 default=list,
209 209 )
210 210 # bundle.mainreporoot: internal hack for bundlerepo
211 211 coreconfigitem(
212 212 b'bundle',
213 213 b'mainreporoot',
214 214 default=b'',
215 215 )
216 216 coreconfigitem(
217 217 b'censor',
218 218 b'policy',
219 219 default=b'abort',
220 220 experimental=True,
221 221 )
222 222 coreconfigitem(
223 223 b'chgserver',
224 224 b'idletimeout',
225 225 default=3600,
226 226 )
227 227 coreconfigitem(
228 228 b'chgserver',
229 229 b'skiphash',
230 230 default=False,
231 231 )
232 232 coreconfigitem(
233 233 b'cmdserver',
234 234 b'log',
235 235 default=None,
236 236 )
237 237 coreconfigitem(
238 238 b'cmdserver',
239 239 b'max-log-files',
240 240 default=7,
241 241 )
242 242 coreconfigitem(
243 243 b'cmdserver',
244 244 b'max-log-size',
245 245 default=b'1 MB',
246 246 )
247 247 coreconfigitem(
248 248 b'cmdserver',
249 249 b'max-repo-cache',
250 250 default=0,
251 251 experimental=True,
252 252 )
253 253 coreconfigitem(
254 254 b'cmdserver',
255 255 b'message-encodings',
256 256 default=list,
257 257 )
258 258 coreconfigitem(
259 259 b'cmdserver',
260 260 b'track-log',
261 261 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
262 262 )
263 263 coreconfigitem(
264 264 b'cmdserver',
265 265 b'shutdown-on-interrupt',
266 266 default=True,
267 267 )
268 268 coreconfigitem(
269 269 b'color',
270 270 b'.*',
271 271 default=None,
272 272 generic=True,
273 273 )
274 274 coreconfigitem(
275 275 b'color',
276 276 b'mode',
277 277 default=b'auto',
278 278 )
279 279 coreconfigitem(
280 280 b'color',
281 281 b'pagermode',
282 282 default=dynamicdefault,
283 283 )
284 284 coreconfigitem(
285 285 b'command-templates',
286 286 b'graphnode',
287 287 default=None,
288 288 alias=[(b'ui', b'graphnodetemplate')],
289 289 )
290 290 coreconfigitem(
291 291 b'command-templates',
292 292 b'log',
293 293 default=None,
294 294 alias=[(b'ui', b'logtemplate')],
295 295 )
296 296 coreconfigitem(
297 297 b'command-templates',
298 298 b'mergemarker',
299 299 default=(
300 300 b'{node|short} '
301 301 b'{ifeq(tags, "tip", "", '
302 302 b'ifeq(tags, "", "", "{tags} "))}'
303 303 b'{if(bookmarks, "{bookmarks} ")}'
304 304 b'{ifeq(branch, "default", "", "{branch} ")}'
305 305 b'- {author|user}: {desc|firstline}'
306 306 ),
307 307 alias=[(b'ui', b'mergemarkertemplate')],
308 308 )
309 309 coreconfigitem(
310 310 b'command-templates',
311 311 b'pre-merge-tool-output',
312 312 default=None,
313 313 alias=[(b'ui', b'pre-merge-tool-output-template')],
314 314 )
315 315 coreconfigitem(
316 316 b'command-templates',
317 317 b'oneline-summary',
318 318 default=None,
319 319 )
320 320 coreconfigitem(
321 321 b'command-templates',
322 322 b'oneline-summary.*',
323 323 default=dynamicdefault,
324 324 generic=True,
325 325 )
326 326 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
327 327 coreconfigitem(
328 328 b'commands',
329 329 b'commit.post-status',
330 330 default=False,
331 331 )
332 332 coreconfigitem(
333 333 b'commands',
334 334 b'grep.all-files',
335 335 default=False,
336 336 experimental=True,
337 337 )
338 338 coreconfigitem(
339 339 b'commands',
340 340 b'merge.require-rev',
341 341 default=False,
342 342 )
343 343 coreconfigitem(
344 344 b'commands',
345 345 b'push.require-revs',
346 346 default=False,
347 347 )
348 348 coreconfigitem(
349 349 b'commands',
350 350 b'resolve.confirm',
351 351 default=False,
352 352 )
353 353 coreconfigitem(
354 354 b'commands',
355 355 b'resolve.explicit-re-merge',
356 356 default=False,
357 357 )
358 358 coreconfigitem(
359 359 b'commands',
360 360 b'resolve.mark-check',
361 361 default=b'none',
362 362 )
363 363 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
364 364 coreconfigitem(
365 365 b'commands',
366 366 b'show.aliasprefix',
367 367 default=list,
368 368 )
369 369 coreconfigitem(
370 370 b'commands',
371 371 b'status.relative',
372 372 default=False,
373 373 )
374 374 coreconfigitem(
375 375 b'commands',
376 376 b'status.skipstates',
377 377 default=[],
378 378 experimental=True,
379 379 )
380 380 coreconfigitem(
381 381 b'commands',
382 382 b'status.terse',
383 383 default=b'',
384 384 )
385 385 coreconfigitem(
386 386 b'commands',
387 387 b'status.verbose',
388 388 default=False,
389 389 )
390 390 coreconfigitem(
391 391 b'commands',
392 392 b'update.check',
393 393 default=None,
394 394 )
395 395 coreconfigitem(
396 396 b'commands',
397 397 b'update.requiredest',
398 398 default=False,
399 399 )
400 400 coreconfigitem(
401 401 b'committemplate',
402 402 b'.*',
403 403 default=None,
404 404 generic=True,
405 405 )
406 406 coreconfigitem(
407 407 b'convert',
408 408 b'bzr.saverev',
409 409 default=True,
410 410 )
411 411 coreconfigitem(
412 412 b'convert',
413 413 b'cvsps.cache',
414 414 default=True,
415 415 )
416 416 coreconfigitem(
417 417 b'convert',
418 418 b'cvsps.fuzz',
419 419 default=60,
420 420 )
421 421 coreconfigitem(
422 422 b'convert',
423 423 b'cvsps.logencoding',
424 424 default=None,
425 425 )
426 426 coreconfigitem(
427 427 b'convert',
428 428 b'cvsps.mergefrom',
429 429 default=None,
430 430 )
431 431 coreconfigitem(
432 432 b'convert',
433 433 b'cvsps.mergeto',
434 434 default=None,
435 435 )
436 436 coreconfigitem(
437 437 b'convert',
438 438 b'git.committeractions',
439 439 default=lambda: [b'messagedifferent'],
440 440 )
441 441 coreconfigitem(
442 442 b'convert',
443 443 b'git.extrakeys',
444 444 default=list,
445 445 )
446 446 coreconfigitem(
447 447 b'convert',
448 448 b'git.findcopiesharder',
449 449 default=False,
450 450 )
451 451 coreconfigitem(
452 452 b'convert',
453 453 b'git.remoteprefix',
454 454 default=b'remote',
455 455 )
456 456 coreconfigitem(
457 457 b'convert',
458 458 b'git.renamelimit',
459 459 default=400,
460 460 )
461 461 coreconfigitem(
462 462 b'convert',
463 463 b'git.saverev',
464 464 default=True,
465 465 )
466 466 coreconfigitem(
467 467 b'convert',
468 468 b'git.similarity',
469 469 default=50,
470 470 )
471 471 coreconfigitem(
472 472 b'convert',
473 473 b'git.skipsubmodules',
474 474 default=False,
475 475 )
476 476 coreconfigitem(
477 477 b'convert',
478 478 b'hg.clonebranches',
479 479 default=False,
480 480 )
481 481 coreconfigitem(
482 482 b'convert',
483 483 b'hg.ignoreerrors',
484 484 default=False,
485 485 )
486 486 coreconfigitem(
487 487 b'convert',
488 488 b'hg.preserve-hash',
489 489 default=False,
490 490 )
491 491 coreconfigitem(
492 492 b'convert',
493 493 b'hg.revs',
494 494 default=None,
495 495 )
496 496 coreconfigitem(
497 497 b'convert',
498 498 b'hg.saverev',
499 499 default=False,
500 500 )
501 501 coreconfigitem(
502 502 b'convert',
503 503 b'hg.sourcename',
504 504 default=None,
505 505 )
506 506 coreconfigitem(
507 507 b'convert',
508 508 b'hg.startrev',
509 509 default=None,
510 510 )
511 511 coreconfigitem(
512 512 b'convert',
513 513 b'hg.tagsbranch',
514 514 default=b'default',
515 515 )
516 516 coreconfigitem(
517 517 b'convert',
518 518 b'hg.usebranchnames',
519 519 default=True,
520 520 )
521 521 coreconfigitem(
522 522 b'convert',
523 523 b'ignoreancestorcheck',
524 524 default=False,
525 525 experimental=True,
526 526 )
527 527 coreconfigitem(
528 528 b'convert',
529 529 b'localtimezone',
530 530 default=False,
531 531 )
532 532 coreconfigitem(
533 533 b'convert',
534 534 b'p4.encoding',
535 535 default=dynamicdefault,
536 536 )
537 537 coreconfigitem(
538 538 b'convert',
539 539 b'p4.startrev',
540 540 default=0,
541 541 )
542 542 coreconfigitem(
543 543 b'convert',
544 544 b'skiptags',
545 545 default=False,
546 546 )
547 547 coreconfigitem(
548 548 b'convert',
549 549 b'svn.debugsvnlog',
550 550 default=True,
551 551 )
552 552 coreconfigitem(
553 553 b'convert',
554 554 b'svn.trunk',
555 555 default=None,
556 556 )
557 557 coreconfigitem(
558 558 b'convert',
559 559 b'svn.tags',
560 560 default=None,
561 561 )
562 562 coreconfigitem(
563 563 b'convert',
564 564 b'svn.branches',
565 565 default=None,
566 566 )
567 567 coreconfigitem(
568 568 b'convert',
569 569 b'svn.startrev',
570 570 default=0,
571 571 )
572 572 coreconfigitem(
573 573 b'convert',
574 574 b'svn.dangerous-set-commit-dates',
575 575 default=False,
576 576 )
577 577 coreconfigitem(
578 578 b'debug',
579 579 b'dirstate.delaywrite',
580 580 default=0,
581 581 )
582 582 coreconfigitem(
583 583 b'defaults',
584 584 b'.*',
585 585 default=None,
586 586 generic=True,
587 587 )
588 588 coreconfigitem(
589 589 b'devel',
590 590 b'all-warnings',
591 591 default=False,
592 592 )
593 593 coreconfigitem(
594 594 b'devel',
595 595 b'bundle2.debug',
596 596 default=False,
597 597 )
598 598 coreconfigitem(
599 599 b'devel',
600 600 b'bundle.delta',
601 601 default=b'',
602 602 )
603 603 coreconfigitem(
604 604 b'devel',
605 605 b'cache-vfs',
606 606 default=None,
607 607 )
608 608 coreconfigitem(
609 609 b'devel',
610 610 b'check-locks',
611 611 default=False,
612 612 )
613 613 coreconfigitem(
614 614 b'devel',
615 615 b'check-relroot',
616 616 default=False,
617 617 )
618 # Track copy information for all file, not just "added" one (very slow)
619 coreconfigitem(
620 b'devel',
621 b'copy-tracing.trace-all-files',
622 default=False,
623 )
618 624 coreconfigitem(
619 625 b'devel',
620 626 b'default-date',
621 627 default=None,
622 628 )
623 629 coreconfigitem(
624 630 b'devel',
625 631 b'deprec-warn',
626 632 default=False,
627 633 )
628 634 coreconfigitem(
629 635 b'devel',
630 636 b'disableloaddefaultcerts',
631 637 default=False,
632 638 )
633 639 coreconfigitem(
634 640 b'devel',
635 641 b'warn-empty-changegroup',
636 642 default=False,
637 643 )
638 644 coreconfigitem(
639 645 b'devel',
640 646 b'legacy.exchange',
641 647 default=list,
642 648 )
643 649 # When True, revlogs use a special reference version of the nodemap, that is not
644 650 # performant but is "known" to behave properly.
645 651 coreconfigitem(
646 652 b'devel',
647 653 b'persistent-nodemap',
648 654 default=False,
649 655 )
650 656 coreconfigitem(
651 657 b'devel',
652 658 b'servercafile',
653 659 default=b'',
654 660 )
655 661 coreconfigitem(
656 662 b'devel',
657 663 b'serverexactprotocol',
658 664 default=b'',
659 665 )
660 666 coreconfigitem(
661 667 b'devel',
662 668 b'serverrequirecert',
663 669 default=False,
664 670 )
665 671 coreconfigitem(
666 672 b'devel',
667 673 b'strip-obsmarkers',
668 674 default=True,
669 675 )
670 676 coreconfigitem(
671 677 b'devel',
672 678 b'warn-config',
673 679 default=None,
674 680 )
675 681 coreconfigitem(
676 682 b'devel',
677 683 b'warn-config-default',
678 684 default=None,
679 685 )
680 686 coreconfigitem(
681 687 b'devel',
682 688 b'user.obsmarker',
683 689 default=None,
684 690 )
685 691 coreconfigitem(
686 692 b'devel',
687 693 b'warn-config-unknown',
688 694 default=None,
689 695 )
690 696 coreconfigitem(
691 697 b'devel',
692 698 b'debug.copies',
693 699 default=False,
694 700 )
695 701 coreconfigitem(
696 702 b'devel',
697 703 b'debug.extensions',
698 704 default=False,
699 705 )
700 706 coreconfigitem(
701 707 b'devel',
702 708 b'debug.repo-filters',
703 709 default=False,
704 710 )
705 711 coreconfigitem(
706 712 b'devel',
707 713 b'debug.peer-request',
708 714 default=False,
709 715 )
710 716 # If discovery.exchange-heads is False, the discovery will not start with
711 717 # remote head fetching and local head querying.
712 718 coreconfigitem(
713 719 b'devel',
714 720 b'discovery.exchange-heads',
715 721 default=True,
716 722 )
717 723 # If discovery.grow-sample is False, the sample size used in set discovery will
718 724 # not be increased through the process
719 725 coreconfigitem(
720 726 b'devel',
721 727 b'discovery.grow-sample',
722 728 default=True,
723 729 )
724 730 # discovery.grow-sample.rate control the rate at which the sample grow
725 731 coreconfigitem(
726 732 b'devel',
727 733 b'discovery.grow-sample.rate',
728 734 default=1.05,
729 735 )
730 736 # If discovery.randomize is False, random sampling during discovery are
731 737 # deterministic. It is meant for integration tests.
732 738 coreconfigitem(
733 739 b'devel',
734 740 b'discovery.randomize',
735 741 default=True,
736 742 )
737 743 # Control the initial size of the discovery sample
738 744 coreconfigitem(
739 745 b'devel',
740 746 b'discovery.sample-size',
741 747 default=200,
742 748 )
743 749 # Control the initial size of the discovery for initial change
744 750 coreconfigitem(
745 751 b'devel',
746 752 b'discovery.sample-size.initial',
747 753 default=100,
748 754 )
749 755 _registerdiffopts(section=b'diff')
750 756 coreconfigitem(
751 757 b'email',
752 758 b'bcc',
753 759 default=None,
754 760 )
755 761 coreconfigitem(
756 762 b'email',
757 763 b'cc',
758 764 default=None,
759 765 )
760 766 coreconfigitem(
761 767 b'email',
762 768 b'charsets',
763 769 default=list,
764 770 )
765 771 coreconfigitem(
766 772 b'email',
767 773 b'from',
768 774 default=None,
769 775 )
770 776 coreconfigitem(
771 777 b'email',
772 778 b'method',
773 779 default=b'smtp',
774 780 )
775 781 coreconfigitem(
776 782 b'email',
777 783 b'reply-to',
778 784 default=None,
779 785 )
780 786 coreconfigitem(
781 787 b'email',
782 788 b'to',
783 789 default=None,
784 790 )
785 791 coreconfigitem(
786 792 b'experimental',
787 793 b'archivemetatemplate',
788 794 default=dynamicdefault,
789 795 )
790 796 coreconfigitem(
791 797 b'experimental',
792 798 b'auto-publish',
793 799 default=b'publish',
794 800 )
795 801 coreconfigitem(
796 802 b'experimental',
797 803 b'bundle-phases',
798 804 default=False,
799 805 )
800 806 coreconfigitem(
801 807 b'experimental',
802 808 b'bundle2-advertise',
803 809 default=True,
804 810 )
805 811 coreconfigitem(
806 812 b'experimental',
807 813 b'bundle2-output-capture',
808 814 default=False,
809 815 )
810 816 coreconfigitem(
811 817 b'experimental',
812 818 b'bundle2.pushback',
813 819 default=False,
814 820 )
815 821 coreconfigitem(
816 822 b'experimental',
817 823 b'bundle2lazylocking',
818 824 default=False,
819 825 )
820 826 coreconfigitem(
821 827 b'experimental',
822 828 b'bundlecomplevel',
823 829 default=None,
824 830 )
825 831 coreconfigitem(
826 832 b'experimental',
827 833 b'bundlecomplevel.bzip2',
828 834 default=None,
829 835 )
830 836 coreconfigitem(
831 837 b'experimental',
832 838 b'bundlecomplevel.gzip',
833 839 default=None,
834 840 )
835 841 coreconfigitem(
836 842 b'experimental',
837 843 b'bundlecomplevel.none',
838 844 default=None,
839 845 )
840 846 coreconfigitem(
841 847 b'experimental',
842 848 b'bundlecomplevel.zstd',
843 849 default=None,
844 850 )
845 851 coreconfigitem(
846 852 b'experimental',
847 853 b'changegroup3',
848 854 default=False,
849 855 )
850 856 coreconfigitem(
851 857 b'experimental',
852 858 b'cleanup-as-archived',
853 859 default=False,
854 860 )
855 861 coreconfigitem(
856 862 b'experimental',
857 863 b'clientcompressionengines',
858 864 default=list,
859 865 )
860 866 coreconfigitem(
861 867 b'experimental',
862 868 b'copytrace',
863 869 default=b'on',
864 870 )
865 871 coreconfigitem(
866 872 b'experimental',
867 873 b'copytrace.movecandidateslimit',
868 874 default=100,
869 875 )
870 876 coreconfigitem(
871 877 b'experimental',
872 878 b'copytrace.sourcecommitlimit',
873 879 default=100,
874 880 )
875 881 coreconfigitem(
876 882 b'experimental',
877 883 b'copies.read-from',
878 884 default=b"filelog-only",
879 885 )
880 886 coreconfigitem(
881 887 b'experimental',
882 888 b'copies.write-to',
883 889 default=b'filelog-only',
884 890 )
885 891 coreconfigitem(
886 892 b'experimental',
887 893 b'crecordtest',
888 894 default=None,
889 895 )
890 896 coreconfigitem(
891 897 b'experimental',
892 898 b'directaccess',
893 899 default=False,
894 900 )
895 901 coreconfigitem(
896 902 b'experimental',
897 903 b'directaccess.revnums',
898 904 default=False,
899 905 )
900 906 coreconfigitem(
901 907 b'experimental',
902 908 b'editortmpinhg',
903 909 default=False,
904 910 )
905 911 coreconfigitem(
906 912 b'experimental',
907 913 b'evolution',
908 914 default=list,
909 915 )
910 916 coreconfigitem(
911 917 b'experimental',
912 918 b'evolution.allowdivergence',
913 919 default=False,
914 920 alias=[(b'experimental', b'allowdivergence')],
915 921 )
916 922 coreconfigitem(
917 923 b'experimental',
918 924 b'evolution.allowunstable',
919 925 default=None,
920 926 )
921 927 coreconfigitem(
922 928 b'experimental',
923 929 b'evolution.createmarkers',
924 930 default=None,
925 931 )
926 932 coreconfigitem(
927 933 b'experimental',
928 934 b'evolution.effect-flags',
929 935 default=True,
930 936 alias=[(b'experimental', b'effect-flags')],
931 937 )
932 938 coreconfigitem(
933 939 b'experimental',
934 940 b'evolution.exchange',
935 941 default=None,
936 942 )
937 943 coreconfigitem(
938 944 b'experimental',
939 945 b'evolution.bundle-obsmarker',
940 946 default=False,
941 947 )
942 948 coreconfigitem(
943 949 b'experimental',
944 950 b'evolution.bundle-obsmarker:mandatory',
945 951 default=True,
946 952 )
947 953 coreconfigitem(
948 954 b'experimental',
949 955 b'log.topo',
950 956 default=False,
951 957 )
952 958 coreconfigitem(
953 959 b'experimental',
954 960 b'evolution.report-instabilities',
955 961 default=True,
956 962 )
957 963 coreconfigitem(
958 964 b'experimental',
959 965 b'evolution.track-operation',
960 966 default=True,
961 967 )
962 968 # repo-level config to exclude a revset visibility
963 969 #
964 970 # The target use case is to use `share` to expose different subset of the same
965 971 # repository, especially server side. See also `server.view`.
966 972 coreconfigitem(
967 973 b'experimental',
968 974 b'extra-filter-revs',
969 975 default=None,
970 976 )
971 977 coreconfigitem(
972 978 b'experimental',
973 979 b'maxdeltachainspan',
974 980 default=-1,
975 981 )
976 982 # tracks files which were undeleted (merge might delete them but we explicitly
977 983 # kept/undeleted them) and creates new filenodes for them
978 984 coreconfigitem(
979 985 b'experimental',
980 986 b'merge-track-salvaged',
981 987 default=False,
982 988 )
983 989 coreconfigitem(
984 990 b'experimental',
985 991 b'mergetempdirprefix',
986 992 default=None,
987 993 )
988 994 coreconfigitem(
989 995 b'experimental',
990 996 b'mmapindexthreshold',
991 997 default=None,
992 998 )
993 999 coreconfigitem(
994 1000 b'experimental',
995 1001 b'narrow',
996 1002 default=False,
997 1003 )
998 1004 coreconfigitem(
999 1005 b'experimental',
1000 1006 b'nonnormalparanoidcheck',
1001 1007 default=False,
1002 1008 )
1003 1009 coreconfigitem(
1004 1010 b'experimental',
1005 1011 b'exportableenviron',
1006 1012 default=list,
1007 1013 )
1008 1014 coreconfigitem(
1009 1015 b'experimental',
1010 1016 b'extendedheader.index',
1011 1017 default=None,
1012 1018 )
1013 1019 coreconfigitem(
1014 1020 b'experimental',
1015 1021 b'extendedheader.similarity',
1016 1022 default=False,
1017 1023 )
1018 1024 coreconfigitem(
1019 1025 b'experimental',
1020 1026 b'graphshorten',
1021 1027 default=False,
1022 1028 )
1023 1029 coreconfigitem(
1024 1030 b'experimental',
1025 1031 b'graphstyle.parent',
1026 1032 default=dynamicdefault,
1027 1033 )
1028 1034 coreconfigitem(
1029 1035 b'experimental',
1030 1036 b'graphstyle.missing',
1031 1037 default=dynamicdefault,
1032 1038 )
1033 1039 coreconfigitem(
1034 1040 b'experimental',
1035 1041 b'graphstyle.grandparent',
1036 1042 default=dynamicdefault,
1037 1043 )
1038 1044 coreconfigitem(
1039 1045 b'experimental',
1040 1046 b'hook-track-tags',
1041 1047 default=False,
1042 1048 )
1043 1049 coreconfigitem(
1044 1050 b'experimental',
1045 1051 b'httppeer.advertise-v2',
1046 1052 default=False,
1047 1053 )
1048 1054 coreconfigitem(
1049 1055 b'experimental',
1050 1056 b'httppeer.v2-encoder-order',
1051 1057 default=None,
1052 1058 )
1053 1059 coreconfigitem(
1054 1060 b'experimental',
1055 1061 b'httppostargs',
1056 1062 default=False,
1057 1063 )
1058 1064 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1059 1065 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1060 1066
1061 1067 coreconfigitem(
1062 1068 b'experimental',
1063 1069 b'obsmarkers-exchange-debug',
1064 1070 default=False,
1065 1071 )
1066 1072 coreconfigitem(
1067 1073 b'experimental',
1068 1074 b'remotenames',
1069 1075 default=False,
1070 1076 )
1071 1077 coreconfigitem(
1072 1078 b'experimental',
1073 1079 b'removeemptydirs',
1074 1080 default=True,
1075 1081 )
1076 1082 coreconfigitem(
1077 1083 b'experimental',
1078 1084 b'revert.interactive.select-to-keep',
1079 1085 default=False,
1080 1086 )
1081 1087 coreconfigitem(
1082 1088 b'experimental',
1083 1089 b'revisions.prefixhexnode',
1084 1090 default=False,
1085 1091 )
1086 1092 coreconfigitem(
1087 1093 b'experimental',
1088 1094 b'revlogv2',
1089 1095 default=None,
1090 1096 )
1091 1097 coreconfigitem(
1092 1098 b'experimental',
1093 1099 b'revisions.disambiguatewithin',
1094 1100 default=None,
1095 1101 )
1096 1102 coreconfigitem(
1097 1103 b'experimental',
1098 1104 b'rust.index',
1099 1105 default=False,
1100 1106 )
1101 1107 coreconfigitem(
1102 1108 b'experimental',
1103 1109 b'server.filesdata.recommended-batch-size',
1104 1110 default=50000,
1105 1111 )
1106 1112 coreconfigitem(
1107 1113 b'experimental',
1108 1114 b'server.manifestdata.recommended-batch-size',
1109 1115 default=100000,
1110 1116 )
1111 1117 coreconfigitem(
1112 1118 b'experimental',
1113 1119 b'server.stream-narrow-clones',
1114 1120 default=False,
1115 1121 )
1116 1122 coreconfigitem(
1117 1123 b'experimental',
1118 1124 b'single-head-per-branch',
1119 1125 default=False,
1120 1126 )
1121 1127 coreconfigitem(
1122 1128 b'experimental',
1123 1129 b'single-head-per-branch:account-closed-heads',
1124 1130 default=False,
1125 1131 )
1126 1132 coreconfigitem(
1127 1133 b'experimental',
1128 1134 b'single-head-per-branch:public-changes-only',
1129 1135 default=False,
1130 1136 )
1131 1137 coreconfigitem(
1132 1138 b'experimental',
1133 1139 b'sshserver.support-v2',
1134 1140 default=False,
1135 1141 )
1136 1142 coreconfigitem(
1137 1143 b'experimental',
1138 1144 b'sparse-read',
1139 1145 default=False,
1140 1146 )
1141 1147 coreconfigitem(
1142 1148 b'experimental',
1143 1149 b'sparse-read.density-threshold',
1144 1150 default=0.50,
1145 1151 )
1146 1152 coreconfigitem(
1147 1153 b'experimental',
1148 1154 b'sparse-read.min-gap-size',
1149 1155 default=b'65K',
1150 1156 )
1151 1157 coreconfigitem(
1152 1158 b'experimental',
1153 1159 b'treemanifest',
1154 1160 default=False,
1155 1161 )
1156 1162 coreconfigitem(
1157 1163 b'experimental',
1158 1164 b'update.atomic-file',
1159 1165 default=False,
1160 1166 )
1161 1167 coreconfigitem(
1162 1168 b'experimental',
1163 1169 b'sshpeer.advertise-v2',
1164 1170 default=False,
1165 1171 )
1166 1172 coreconfigitem(
1167 1173 b'experimental',
1168 1174 b'web.apiserver',
1169 1175 default=False,
1170 1176 )
1171 1177 coreconfigitem(
1172 1178 b'experimental',
1173 1179 b'web.api.http-v2',
1174 1180 default=False,
1175 1181 )
1176 1182 coreconfigitem(
1177 1183 b'experimental',
1178 1184 b'web.api.debugreflect',
1179 1185 default=False,
1180 1186 )
1181 1187 coreconfigitem(
1182 1188 b'experimental',
1183 1189 b'worker.wdir-get-thread-safe',
1184 1190 default=False,
1185 1191 )
1186 1192 coreconfigitem(
1187 1193 b'experimental',
1188 1194 b'worker.repository-upgrade',
1189 1195 default=False,
1190 1196 )
1191 1197 coreconfigitem(
1192 1198 b'experimental',
1193 1199 b'xdiff',
1194 1200 default=False,
1195 1201 )
1196 1202 coreconfigitem(
1197 1203 b'extensions',
1198 1204 b'.*',
1199 1205 default=None,
1200 1206 generic=True,
1201 1207 )
1202 1208 coreconfigitem(
1203 1209 b'extdata',
1204 1210 b'.*',
1205 1211 default=None,
1206 1212 generic=True,
1207 1213 )
1208 1214 coreconfigitem(
1209 1215 b'format',
1210 1216 b'bookmarks-in-store',
1211 1217 default=False,
1212 1218 )
1213 1219 coreconfigitem(
1214 1220 b'format',
1215 1221 b'chunkcachesize',
1216 1222 default=None,
1217 1223 experimental=True,
1218 1224 )
1219 1225 coreconfigitem(
1220 1226 b'format',
1221 1227 b'dotencode',
1222 1228 default=True,
1223 1229 )
1224 1230 coreconfigitem(
1225 1231 b'format',
1226 1232 b'generaldelta',
1227 1233 default=False,
1228 1234 experimental=True,
1229 1235 )
1230 1236 coreconfigitem(
1231 1237 b'format',
1232 1238 b'manifestcachesize',
1233 1239 default=None,
1234 1240 experimental=True,
1235 1241 )
1236 1242 coreconfigitem(
1237 1243 b'format',
1238 1244 b'maxchainlen',
1239 1245 default=dynamicdefault,
1240 1246 experimental=True,
1241 1247 )
1242 1248 coreconfigitem(
1243 1249 b'format',
1244 1250 b'obsstore-version',
1245 1251 default=None,
1246 1252 )
1247 1253 coreconfigitem(
1248 1254 b'format',
1249 1255 b'sparse-revlog',
1250 1256 default=True,
1251 1257 )
1252 1258 coreconfigitem(
1253 1259 b'format',
1254 1260 b'revlog-compression',
1255 1261 default=lambda: [b'zlib'],
1256 1262 alias=[(b'experimental', b'format.compression')],
1257 1263 )
1258 1264 coreconfigitem(
1259 1265 b'format',
1260 1266 b'usefncache',
1261 1267 default=True,
1262 1268 )
1263 1269 coreconfigitem(
1264 1270 b'format',
1265 1271 b'usegeneraldelta',
1266 1272 default=True,
1267 1273 )
1268 1274 coreconfigitem(
1269 1275 b'format',
1270 1276 b'usestore',
1271 1277 default=True,
1272 1278 )
1273 1279 coreconfigitem(
1274 1280 b'format',
1275 1281 b'use-persistent-nodemap',
1276 1282 default=False,
1277 1283 )
1278 1284 coreconfigitem(
1279 1285 b'format',
1280 1286 b'exp-use-copies-side-data-changeset',
1281 1287 default=False,
1282 1288 experimental=True,
1283 1289 )
1284 1290 coreconfigitem(
1285 1291 b'format',
1286 1292 b'exp-use-side-data',
1287 1293 default=False,
1288 1294 experimental=True,
1289 1295 )
1290 1296 coreconfigitem(
1291 1297 b'format',
1292 1298 b'use-share-safe',
1293 1299 default=False,
1294 1300 )
1295 1301 coreconfigitem(
1296 1302 b'format',
1297 1303 b'internal-phase',
1298 1304 default=False,
1299 1305 experimental=True,
1300 1306 )
1301 1307 coreconfigitem(
1302 1308 b'fsmonitor',
1303 1309 b'warn_when_unused',
1304 1310 default=True,
1305 1311 )
1306 1312 coreconfigitem(
1307 1313 b'fsmonitor',
1308 1314 b'warn_update_file_count',
1309 1315 default=50000,
1310 1316 )
1311 1317 coreconfigitem(
1312 1318 b'fsmonitor',
1313 1319 b'warn_update_file_count_rust',
1314 1320 default=400000,
1315 1321 )
1316 1322 coreconfigitem(
1317 1323 b'help',
1318 1324 br'hidden-command\..*',
1319 1325 default=False,
1320 1326 generic=True,
1321 1327 )
1322 1328 coreconfigitem(
1323 1329 b'help',
1324 1330 br'hidden-topic\..*',
1325 1331 default=False,
1326 1332 generic=True,
1327 1333 )
1328 1334 coreconfigitem(
1329 1335 b'hooks',
1330 1336 b'.*',
1331 1337 default=dynamicdefault,
1332 1338 generic=True,
1333 1339 )
1334 1340 coreconfigitem(
1335 1341 b'hgweb-paths',
1336 1342 b'.*',
1337 1343 default=list,
1338 1344 generic=True,
1339 1345 )
1340 1346 coreconfigitem(
1341 1347 b'hostfingerprints',
1342 1348 b'.*',
1343 1349 default=list,
1344 1350 generic=True,
1345 1351 )
1346 1352 coreconfigitem(
1347 1353 b'hostsecurity',
1348 1354 b'ciphers',
1349 1355 default=None,
1350 1356 )
1351 1357 coreconfigitem(
1352 1358 b'hostsecurity',
1353 1359 b'minimumprotocol',
1354 1360 default=dynamicdefault,
1355 1361 )
1356 1362 coreconfigitem(
1357 1363 b'hostsecurity',
1358 1364 b'.*:minimumprotocol$',
1359 1365 default=dynamicdefault,
1360 1366 generic=True,
1361 1367 )
1362 1368 coreconfigitem(
1363 1369 b'hostsecurity',
1364 1370 b'.*:ciphers$',
1365 1371 default=dynamicdefault,
1366 1372 generic=True,
1367 1373 )
1368 1374 coreconfigitem(
1369 1375 b'hostsecurity',
1370 1376 b'.*:fingerprints$',
1371 1377 default=list,
1372 1378 generic=True,
1373 1379 )
1374 1380 coreconfigitem(
1375 1381 b'hostsecurity',
1376 1382 b'.*:verifycertsfile$',
1377 1383 default=None,
1378 1384 generic=True,
1379 1385 )
1380 1386
1381 1387 coreconfigitem(
1382 1388 b'http_proxy',
1383 1389 b'always',
1384 1390 default=False,
1385 1391 )
1386 1392 coreconfigitem(
1387 1393 b'http_proxy',
1388 1394 b'host',
1389 1395 default=None,
1390 1396 )
1391 1397 coreconfigitem(
1392 1398 b'http_proxy',
1393 1399 b'no',
1394 1400 default=list,
1395 1401 )
1396 1402 coreconfigitem(
1397 1403 b'http_proxy',
1398 1404 b'passwd',
1399 1405 default=None,
1400 1406 )
1401 1407 coreconfigitem(
1402 1408 b'http_proxy',
1403 1409 b'user',
1404 1410 default=None,
1405 1411 )
1406 1412
1407 1413 coreconfigitem(
1408 1414 b'http',
1409 1415 b'timeout',
1410 1416 default=None,
1411 1417 )
1412 1418
1413 1419 coreconfigitem(
1414 1420 b'logtoprocess',
1415 1421 b'commandexception',
1416 1422 default=None,
1417 1423 )
1418 1424 coreconfigitem(
1419 1425 b'logtoprocess',
1420 1426 b'commandfinish',
1421 1427 default=None,
1422 1428 )
1423 1429 coreconfigitem(
1424 1430 b'logtoprocess',
1425 1431 b'command',
1426 1432 default=None,
1427 1433 )
1428 1434 coreconfigitem(
1429 1435 b'logtoprocess',
1430 1436 b'develwarn',
1431 1437 default=None,
1432 1438 )
1433 1439 coreconfigitem(
1434 1440 b'logtoprocess',
1435 1441 b'uiblocked',
1436 1442 default=None,
1437 1443 )
1438 1444 coreconfigitem(
1439 1445 b'merge',
1440 1446 b'checkunknown',
1441 1447 default=b'abort',
1442 1448 )
1443 1449 coreconfigitem(
1444 1450 b'merge',
1445 1451 b'checkignored',
1446 1452 default=b'abort',
1447 1453 )
1448 1454 coreconfigitem(
1449 1455 b'experimental',
1450 1456 b'merge.checkpathconflicts',
1451 1457 default=False,
1452 1458 )
1453 1459 coreconfigitem(
1454 1460 b'merge',
1455 1461 b'followcopies',
1456 1462 default=True,
1457 1463 )
1458 1464 coreconfigitem(
1459 1465 b'merge',
1460 1466 b'on-failure',
1461 1467 default=b'continue',
1462 1468 )
1463 1469 coreconfigitem(
1464 1470 b'merge',
1465 1471 b'preferancestor',
1466 1472 default=lambda: [b'*'],
1467 1473 experimental=True,
1468 1474 )
1469 1475 coreconfigitem(
1470 1476 b'merge',
1471 1477 b'strict-capability-check',
1472 1478 default=False,
1473 1479 )
1474 1480 coreconfigitem(
1475 1481 b'merge-tools',
1476 1482 b'.*',
1477 1483 default=None,
1478 1484 generic=True,
1479 1485 )
1480 1486 coreconfigitem(
1481 1487 b'merge-tools',
1482 1488 br'.*\.args$',
1483 1489 default=b"$local $base $other",
1484 1490 generic=True,
1485 1491 priority=-1,
1486 1492 )
1487 1493 coreconfigitem(
1488 1494 b'merge-tools',
1489 1495 br'.*\.binary$',
1490 1496 default=False,
1491 1497 generic=True,
1492 1498 priority=-1,
1493 1499 )
1494 1500 coreconfigitem(
1495 1501 b'merge-tools',
1496 1502 br'.*\.check$',
1497 1503 default=list,
1498 1504 generic=True,
1499 1505 priority=-1,
1500 1506 )
1501 1507 coreconfigitem(
1502 1508 b'merge-tools',
1503 1509 br'.*\.checkchanged$',
1504 1510 default=False,
1505 1511 generic=True,
1506 1512 priority=-1,
1507 1513 )
1508 1514 coreconfigitem(
1509 1515 b'merge-tools',
1510 1516 br'.*\.executable$',
1511 1517 default=dynamicdefault,
1512 1518 generic=True,
1513 1519 priority=-1,
1514 1520 )
1515 1521 coreconfigitem(
1516 1522 b'merge-tools',
1517 1523 br'.*\.fixeol$',
1518 1524 default=False,
1519 1525 generic=True,
1520 1526 priority=-1,
1521 1527 )
1522 1528 coreconfigitem(
1523 1529 b'merge-tools',
1524 1530 br'.*\.gui$',
1525 1531 default=False,
1526 1532 generic=True,
1527 1533 priority=-1,
1528 1534 )
1529 1535 coreconfigitem(
1530 1536 b'merge-tools',
1531 1537 br'.*\.mergemarkers$',
1532 1538 default=b'basic',
1533 1539 generic=True,
1534 1540 priority=-1,
1535 1541 )
1536 1542 coreconfigitem(
1537 1543 b'merge-tools',
1538 1544 br'.*\.mergemarkertemplate$',
1539 1545 default=dynamicdefault, # take from command-templates.mergemarker
1540 1546 generic=True,
1541 1547 priority=-1,
1542 1548 )
1543 1549 coreconfigitem(
1544 1550 b'merge-tools',
1545 1551 br'.*\.priority$',
1546 1552 default=0,
1547 1553 generic=True,
1548 1554 priority=-1,
1549 1555 )
1550 1556 coreconfigitem(
1551 1557 b'merge-tools',
1552 1558 br'.*\.premerge$',
1553 1559 default=dynamicdefault,
1554 1560 generic=True,
1555 1561 priority=-1,
1556 1562 )
1557 1563 coreconfigitem(
1558 1564 b'merge-tools',
1559 1565 br'.*\.symlink$',
1560 1566 default=False,
1561 1567 generic=True,
1562 1568 priority=-1,
1563 1569 )
1564 1570 coreconfigitem(
1565 1571 b'pager',
1566 1572 b'attend-.*',
1567 1573 default=dynamicdefault,
1568 1574 generic=True,
1569 1575 )
1570 1576 coreconfigitem(
1571 1577 b'pager',
1572 1578 b'ignore',
1573 1579 default=list,
1574 1580 )
1575 1581 coreconfigitem(
1576 1582 b'pager',
1577 1583 b'pager',
1578 1584 default=dynamicdefault,
1579 1585 )
1580 1586 coreconfigitem(
1581 1587 b'patch',
1582 1588 b'eol',
1583 1589 default=b'strict',
1584 1590 )
1585 1591 coreconfigitem(
1586 1592 b'patch',
1587 1593 b'fuzz',
1588 1594 default=2,
1589 1595 )
1590 1596 coreconfigitem(
1591 1597 b'paths',
1592 1598 b'default',
1593 1599 default=None,
1594 1600 )
1595 1601 coreconfigitem(
1596 1602 b'paths',
1597 1603 b'default-push',
1598 1604 default=None,
1599 1605 )
1600 1606 coreconfigitem(
1601 1607 b'paths',
1602 1608 b'.*',
1603 1609 default=None,
1604 1610 generic=True,
1605 1611 )
1606 1612 coreconfigitem(
1607 1613 b'phases',
1608 1614 b'checksubrepos',
1609 1615 default=b'follow',
1610 1616 )
1611 1617 coreconfigitem(
1612 1618 b'phases',
1613 1619 b'new-commit',
1614 1620 default=b'draft',
1615 1621 )
1616 1622 coreconfigitem(
1617 1623 b'phases',
1618 1624 b'publish',
1619 1625 default=True,
1620 1626 )
1621 1627 coreconfigitem(
1622 1628 b'profiling',
1623 1629 b'enabled',
1624 1630 default=False,
1625 1631 )
1626 1632 coreconfigitem(
1627 1633 b'profiling',
1628 1634 b'format',
1629 1635 default=b'text',
1630 1636 )
1631 1637 coreconfigitem(
1632 1638 b'profiling',
1633 1639 b'freq',
1634 1640 default=1000,
1635 1641 )
1636 1642 coreconfigitem(
1637 1643 b'profiling',
1638 1644 b'limit',
1639 1645 default=30,
1640 1646 )
1641 1647 coreconfigitem(
1642 1648 b'profiling',
1643 1649 b'nested',
1644 1650 default=0,
1645 1651 )
1646 1652 coreconfigitem(
1647 1653 b'profiling',
1648 1654 b'output',
1649 1655 default=None,
1650 1656 )
1651 1657 coreconfigitem(
1652 1658 b'profiling',
1653 1659 b'showmax',
1654 1660 default=0.999,
1655 1661 )
1656 1662 coreconfigitem(
1657 1663 b'profiling',
1658 1664 b'showmin',
1659 1665 default=dynamicdefault,
1660 1666 )
1661 1667 coreconfigitem(
1662 1668 b'profiling',
1663 1669 b'showtime',
1664 1670 default=True,
1665 1671 )
1666 1672 coreconfigitem(
1667 1673 b'profiling',
1668 1674 b'sort',
1669 1675 default=b'inlinetime',
1670 1676 )
1671 1677 coreconfigitem(
1672 1678 b'profiling',
1673 1679 b'statformat',
1674 1680 default=b'hotpath',
1675 1681 )
1676 1682 coreconfigitem(
1677 1683 b'profiling',
1678 1684 b'time-track',
1679 1685 default=dynamicdefault,
1680 1686 )
1681 1687 coreconfigitem(
1682 1688 b'profiling',
1683 1689 b'type',
1684 1690 default=b'stat',
1685 1691 )
1686 1692 coreconfigitem(
1687 1693 b'progress',
1688 1694 b'assume-tty',
1689 1695 default=False,
1690 1696 )
1691 1697 coreconfigitem(
1692 1698 b'progress',
1693 1699 b'changedelay',
1694 1700 default=1,
1695 1701 )
1696 1702 coreconfigitem(
1697 1703 b'progress',
1698 1704 b'clear-complete',
1699 1705 default=True,
1700 1706 )
1701 1707 coreconfigitem(
1702 1708 b'progress',
1703 1709 b'debug',
1704 1710 default=False,
1705 1711 )
1706 1712 coreconfigitem(
1707 1713 b'progress',
1708 1714 b'delay',
1709 1715 default=3,
1710 1716 )
1711 1717 coreconfigitem(
1712 1718 b'progress',
1713 1719 b'disable',
1714 1720 default=False,
1715 1721 )
1716 1722 coreconfigitem(
1717 1723 b'progress',
1718 1724 b'estimateinterval',
1719 1725 default=60.0,
1720 1726 )
1721 1727 coreconfigitem(
1722 1728 b'progress',
1723 1729 b'format',
1724 1730 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
1725 1731 )
1726 1732 coreconfigitem(
1727 1733 b'progress',
1728 1734 b'refresh',
1729 1735 default=0.1,
1730 1736 )
1731 1737 coreconfigitem(
1732 1738 b'progress',
1733 1739 b'width',
1734 1740 default=dynamicdefault,
1735 1741 )
1736 1742 coreconfigitem(
1737 1743 b'pull',
1738 1744 b'confirm',
1739 1745 default=False,
1740 1746 )
1741 1747 coreconfigitem(
1742 1748 b'push',
1743 1749 b'pushvars.server',
1744 1750 default=False,
1745 1751 )
1746 1752 coreconfigitem(
1747 1753 b'rewrite',
1748 1754 b'backup-bundle',
1749 1755 default=True,
1750 1756 alias=[(b'ui', b'history-editing-backup')],
1751 1757 )
1752 1758 coreconfigitem(
1753 1759 b'rewrite',
1754 1760 b'update-timestamp',
1755 1761 default=False,
1756 1762 )
1757 1763 coreconfigitem(
1758 1764 b'rewrite',
1759 1765 b'empty-successor',
1760 1766 default=b'skip',
1761 1767 experimental=True,
1762 1768 )
1763 1769 coreconfigitem(
1764 1770 b'storage',
1765 1771 b'new-repo-backend',
1766 1772 default=b'revlogv1',
1767 1773 experimental=True,
1768 1774 )
1769 1775 coreconfigitem(
1770 1776 b'storage',
1771 1777 b'revlog.optimize-delta-parent-choice',
1772 1778 default=True,
1773 1779 alias=[(b'format', b'aggressivemergedeltas')],
1774 1780 )
1775 1781 # experimental as long as rust is experimental (or a C version is implemented)
1776 1782 coreconfigitem(
1777 1783 b'storage',
1778 1784 b'revlog.persistent-nodemap.mmap',
1779 1785 default=True,
1780 1786 )
1781 1787 # experimental as long as format.use-persistent-nodemap is.
1782 1788 coreconfigitem(
1783 1789 b'storage',
1784 1790 b'revlog.persistent-nodemap.slow-path',
1785 1791 default=b"abort",
1786 1792 )
1787 1793
1788 1794 coreconfigitem(
1789 1795 b'storage',
1790 1796 b'revlog.reuse-external-delta',
1791 1797 default=True,
1792 1798 )
1793 1799 coreconfigitem(
1794 1800 b'storage',
1795 1801 b'revlog.reuse-external-delta-parent',
1796 1802 default=None,
1797 1803 )
1798 1804 coreconfigitem(
1799 1805 b'storage',
1800 1806 b'revlog.zlib.level',
1801 1807 default=None,
1802 1808 )
1803 1809 coreconfigitem(
1804 1810 b'storage',
1805 1811 b'revlog.zstd.level',
1806 1812 default=None,
1807 1813 )
1808 1814 coreconfigitem(
1809 1815 b'server',
1810 1816 b'bookmarks-pushkey-compat',
1811 1817 default=True,
1812 1818 )
1813 1819 coreconfigitem(
1814 1820 b'server',
1815 1821 b'bundle1',
1816 1822 default=True,
1817 1823 )
1818 1824 coreconfigitem(
1819 1825 b'server',
1820 1826 b'bundle1gd',
1821 1827 default=None,
1822 1828 )
1823 1829 coreconfigitem(
1824 1830 b'server',
1825 1831 b'bundle1.pull',
1826 1832 default=None,
1827 1833 )
1828 1834 coreconfigitem(
1829 1835 b'server',
1830 1836 b'bundle1gd.pull',
1831 1837 default=None,
1832 1838 )
1833 1839 coreconfigitem(
1834 1840 b'server',
1835 1841 b'bundle1.push',
1836 1842 default=None,
1837 1843 )
1838 1844 coreconfigitem(
1839 1845 b'server',
1840 1846 b'bundle1gd.push',
1841 1847 default=None,
1842 1848 )
1843 1849 coreconfigitem(
1844 1850 b'server',
1845 1851 b'bundle2.stream',
1846 1852 default=True,
1847 1853 alias=[(b'experimental', b'bundle2.stream')],
1848 1854 )
1849 1855 coreconfigitem(
1850 1856 b'server',
1851 1857 b'compressionengines',
1852 1858 default=list,
1853 1859 )
1854 1860 coreconfigitem(
1855 1861 b'server',
1856 1862 b'concurrent-push-mode',
1857 1863 default=b'check-related',
1858 1864 )
1859 1865 coreconfigitem(
1860 1866 b'server',
1861 1867 b'disablefullbundle',
1862 1868 default=False,
1863 1869 )
1864 1870 coreconfigitem(
1865 1871 b'server',
1866 1872 b'maxhttpheaderlen',
1867 1873 default=1024,
1868 1874 )
1869 1875 coreconfigitem(
1870 1876 b'server',
1871 1877 b'pullbundle',
1872 1878 default=False,
1873 1879 )
1874 1880 coreconfigitem(
1875 1881 b'server',
1876 1882 b'preferuncompressed',
1877 1883 default=False,
1878 1884 )
1879 1885 coreconfigitem(
1880 1886 b'server',
1881 1887 b'streamunbundle',
1882 1888 default=False,
1883 1889 )
1884 1890 coreconfigitem(
1885 1891 b'server',
1886 1892 b'uncompressed',
1887 1893 default=True,
1888 1894 )
1889 1895 coreconfigitem(
1890 1896 b'server',
1891 1897 b'uncompressedallowsecret',
1892 1898 default=False,
1893 1899 )
1894 1900 coreconfigitem(
1895 1901 b'server',
1896 1902 b'view',
1897 1903 default=b'served',
1898 1904 )
1899 1905 coreconfigitem(
1900 1906 b'server',
1901 1907 b'validate',
1902 1908 default=False,
1903 1909 )
1904 1910 coreconfigitem(
1905 1911 b'server',
1906 1912 b'zliblevel',
1907 1913 default=-1,
1908 1914 )
1909 1915 coreconfigitem(
1910 1916 b'server',
1911 1917 b'zstdlevel',
1912 1918 default=3,
1913 1919 )
1914 1920 coreconfigitem(
1915 1921 b'share',
1916 1922 b'pool',
1917 1923 default=None,
1918 1924 )
1919 1925 coreconfigitem(
1920 1926 b'share',
1921 1927 b'poolnaming',
1922 1928 default=b'identity',
1923 1929 )
1924 1930 coreconfigitem(
1925 1931 b'share',
1926 1932 b'safe-mismatch.source-not-safe',
1927 1933 default=b'abort',
1928 1934 )
1929 1935 coreconfigitem(
1930 1936 b'share',
1931 1937 b'safe-mismatch.source-safe',
1932 1938 default=b'abort',
1933 1939 )
1934 1940 coreconfigitem(
1935 1941 b'share',
1936 1942 b'safe-mismatch.source-not-safe.warn',
1937 1943 default=True,
1938 1944 )
1939 1945 coreconfigitem(
1940 1946 b'share',
1941 1947 b'safe-mismatch.source-safe.warn',
1942 1948 default=True,
1943 1949 )
1944 1950 coreconfigitem(
1945 1951 b'shelve',
1946 1952 b'maxbackups',
1947 1953 default=10,
1948 1954 )
1949 1955 coreconfigitem(
1950 1956 b'smtp',
1951 1957 b'host',
1952 1958 default=None,
1953 1959 )
1954 1960 coreconfigitem(
1955 1961 b'smtp',
1956 1962 b'local_hostname',
1957 1963 default=None,
1958 1964 )
1959 1965 coreconfigitem(
1960 1966 b'smtp',
1961 1967 b'password',
1962 1968 default=None,
1963 1969 )
1964 1970 coreconfigitem(
1965 1971 b'smtp',
1966 1972 b'port',
1967 1973 default=dynamicdefault,
1968 1974 )
1969 1975 coreconfigitem(
1970 1976 b'smtp',
1971 1977 b'tls',
1972 1978 default=b'none',
1973 1979 )
1974 1980 coreconfigitem(
1975 1981 b'smtp',
1976 1982 b'username',
1977 1983 default=None,
1978 1984 )
1979 1985 coreconfigitem(
1980 1986 b'sparse',
1981 1987 b'missingwarning',
1982 1988 default=True,
1983 1989 experimental=True,
1984 1990 )
1985 1991 coreconfigitem(
1986 1992 b'subrepos',
1987 1993 b'allowed',
1988 1994 default=dynamicdefault, # to make backporting simpler
1989 1995 )
1990 1996 coreconfigitem(
1991 1997 b'subrepos',
1992 1998 b'hg:allowed',
1993 1999 default=dynamicdefault,
1994 2000 )
1995 2001 coreconfigitem(
1996 2002 b'subrepos',
1997 2003 b'git:allowed',
1998 2004 default=dynamicdefault,
1999 2005 )
2000 2006 coreconfigitem(
2001 2007 b'subrepos',
2002 2008 b'svn:allowed',
2003 2009 default=dynamicdefault,
2004 2010 )
2005 2011 coreconfigitem(
2006 2012 b'templates',
2007 2013 b'.*',
2008 2014 default=None,
2009 2015 generic=True,
2010 2016 )
2011 2017 coreconfigitem(
2012 2018 b'templateconfig',
2013 2019 b'.*',
2014 2020 default=dynamicdefault,
2015 2021 generic=True,
2016 2022 )
2017 2023 coreconfigitem(
2018 2024 b'trusted',
2019 2025 b'groups',
2020 2026 default=list,
2021 2027 )
2022 2028 coreconfigitem(
2023 2029 b'trusted',
2024 2030 b'users',
2025 2031 default=list,
2026 2032 )
2027 2033 coreconfigitem(
2028 2034 b'ui',
2029 2035 b'_usedassubrepo',
2030 2036 default=False,
2031 2037 )
2032 2038 coreconfigitem(
2033 2039 b'ui',
2034 2040 b'allowemptycommit',
2035 2041 default=False,
2036 2042 )
2037 2043 coreconfigitem(
2038 2044 b'ui',
2039 2045 b'archivemeta',
2040 2046 default=True,
2041 2047 )
2042 2048 coreconfigitem(
2043 2049 b'ui',
2044 2050 b'askusername',
2045 2051 default=False,
2046 2052 )
2047 2053 coreconfigitem(
2048 2054 b'ui',
2049 2055 b'available-memory',
2050 2056 default=None,
2051 2057 )
2052 2058
2053 2059 coreconfigitem(
2054 2060 b'ui',
2055 2061 b'clonebundlefallback',
2056 2062 default=False,
2057 2063 )
2058 2064 coreconfigitem(
2059 2065 b'ui',
2060 2066 b'clonebundleprefers',
2061 2067 default=list,
2062 2068 )
2063 2069 coreconfigitem(
2064 2070 b'ui',
2065 2071 b'clonebundles',
2066 2072 default=True,
2067 2073 )
2068 2074 coreconfigitem(
2069 2075 b'ui',
2070 2076 b'color',
2071 2077 default=b'auto',
2072 2078 )
2073 2079 coreconfigitem(
2074 2080 b'ui',
2075 2081 b'commitsubrepos',
2076 2082 default=False,
2077 2083 )
2078 2084 coreconfigitem(
2079 2085 b'ui',
2080 2086 b'debug',
2081 2087 default=False,
2082 2088 )
2083 2089 coreconfigitem(
2084 2090 b'ui',
2085 2091 b'debugger',
2086 2092 default=None,
2087 2093 )
2088 2094 coreconfigitem(
2089 2095 b'ui',
2090 2096 b'editor',
2091 2097 default=dynamicdefault,
2092 2098 )
2093 2099 coreconfigitem(
2094 2100 b'ui',
2095 2101 b'detailed-exit-code',
2096 2102 default=False,
2097 2103 experimental=True,
2098 2104 )
2099 2105 coreconfigitem(
2100 2106 b'ui',
2101 2107 b'fallbackencoding',
2102 2108 default=None,
2103 2109 )
2104 2110 coreconfigitem(
2105 2111 b'ui',
2106 2112 b'forcecwd',
2107 2113 default=None,
2108 2114 )
2109 2115 coreconfigitem(
2110 2116 b'ui',
2111 2117 b'forcemerge',
2112 2118 default=None,
2113 2119 )
2114 2120 coreconfigitem(
2115 2121 b'ui',
2116 2122 b'formatdebug',
2117 2123 default=False,
2118 2124 )
2119 2125 coreconfigitem(
2120 2126 b'ui',
2121 2127 b'formatjson',
2122 2128 default=False,
2123 2129 )
2124 2130 coreconfigitem(
2125 2131 b'ui',
2126 2132 b'formatted',
2127 2133 default=None,
2128 2134 )
2129 2135 coreconfigitem(
2130 2136 b'ui',
2131 2137 b'interactive',
2132 2138 default=None,
2133 2139 )
2134 2140 coreconfigitem(
2135 2141 b'ui',
2136 2142 b'interface',
2137 2143 default=None,
2138 2144 )
2139 2145 coreconfigitem(
2140 2146 b'ui',
2141 2147 b'interface.chunkselector',
2142 2148 default=None,
2143 2149 )
2144 2150 coreconfigitem(
2145 2151 b'ui',
2146 2152 b'large-file-limit',
2147 2153 default=10000000,
2148 2154 )
2149 2155 coreconfigitem(
2150 2156 b'ui',
2151 2157 b'logblockedtimes',
2152 2158 default=False,
2153 2159 )
2154 2160 coreconfigitem(
2155 2161 b'ui',
2156 2162 b'merge',
2157 2163 default=None,
2158 2164 )
2159 2165 coreconfigitem(
2160 2166 b'ui',
2161 2167 b'mergemarkers',
2162 2168 default=b'basic',
2163 2169 )
2164 2170 coreconfigitem(
2165 2171 b'ui',
2166 2172 b'message-output',
2167 2173 default=b'stdio',
2168 2174 )
2169 2175 coreconfigitem(
2170 2176 b'ui',
2171 2177 b'nontty',
2172 2178 default=False,
2173 2179 )
2174 2180 coreconfigitem(
2175 2181 b'ui',
2176 2182 b'origbackuppath',
2177 2183 default=None,
2178 2184 )
2179 2185 coreconfigitem(
2180 2186 b'ui',
2181 2187 b'paginate',
2182 2188 default=True,
2183 2189 )
2184 2190 coreconfigitem(
2185 2191 b'ui',
2186 2192 b'patch',
2187 2193 default=None,
2188 2194 )
2189 2195 coreconfigitem(
2190 2196 b'ui',
2191 2197 b'portablefilenames',
2192 2198 default=b'warn',
2193 2199 )
2194 2200 coreconfigitem(
2195 2201 b'ui',
2196 2202 b'promptecho',
2197 2203 default=False,
2198 2204 )
2199 2205 coreconfigitem(
2200 2206 b'ui',
2201 2207 b'quiet',
2202 2208 default=False,
2203 2209 )
2204 2210 coreconfigitem(
2205 2211 b'ui',
2206 2212 b'quietbookmarkmove',
2207 2213 default=False,
2208 2214 )
2209 2215 coreconfigitem(
2210 2216 b'ui',
2211 2217 b'relative-paths',
2212 2218 default=b'legacy',
2213 2219 )
2214 2220 coreconfigitem(
2215 2221 b'ui',
2216 2222 b'remotecmd',
2217 2223 default=b'hg',
2218 2224 )
2219 2225 coreconfigitem(
2220 2226 b'ui',
2221 2227 b'report_untrusted',
2222 2228 default=True,
2223 2229 )
2224 2230 coreconfigitem(
2225 2231 b'ui',
2226 2232 b'rollback',
2227 2233 default=True,
2228 2234 )
2229 2235 coreconfigitem(
2230 2236 b'ui',
2231 2237 b'signal-safe-lock',
2232 2238 default=True,
2233 2239 )
2234 2240 coreconfigitem(
2235 2241 b'ui',
2236 2242 b'slash',
2237 2243 default=False,
2238 2244 )
2239 2245 coreconfigitem(
2240 2246 b'ui',
2241 2247 b'ssh',
2242 2248 default=b'ssh',
2243 2249 )
2244 2250 coreconfigitem(
2245 2251 b'ui',
2246 2252 b'ssherrorhint',
2247 2253 default=None,
2248 2254 )
2249 2255 coreconfigitem(
2250 2256 b'ui',
2251 2257 b'statuscopies',
2252 2258 default=False,
2253 2259 )
2254 2260 coreconfigitem(
2255 2261 b'ui',
2256 2262 b'strict',
2257 2263 default=False,
2258 2264 )
2259 2265 coreconfigitem(
2260 2266 b'ui',
2261 2267 b'style',
2262 2268 default=b'',
2263 2269 )
2264 2270 coreconfigitem(
2265 2271 b'ui',
2266 2272 b'supportcontact',
2267 2273 default=None,
2268 2274 )
2269 2275 coreconfigitem(
2270 2276 b'ui',
2271 2277 b'textwidth',
2272 2278 default=78,
2273 2279 )
2274 2280 coreconfigitem(
2275 2281 b'ui',
2276 2282 b'timeout',
2277 2283 default=b'600',
2278 2284 )
2279 2285 coreconfigitem(
2280 2286 b'ui',
2281 2287 b'timeout.warn',
2282 2288 default=0,
2283 2289 )
2284 2290 coreconfigitem(
2285 2291 b'ui',
2286 2292 b'timestamp-output',
2287 2293 default=False,
2288 2294 )
2289 2295 coreconfigitem(
2290 2296 b'ui',
2291 2297 b'traceback',
2292 2298 default=False,
2293 2299 )
2294 2300 coreconfigitem(
2295 2301 b'ui',
2296 2302 b'tweakdefaults',
2297 2303 default=False,
2298 2304 )
2299 2305 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2300 2306 coreconfigitem(
2301 2307 b'ui',
2302 2308 b'verbose',
2303 2309 default=False,
2304 2310 )
2305 2311 coreconfigitem(
2306 2312 b'verify',
2307 2313 b'skipflags',
2308 2314 default=None,
2309 2315 )
2310 2316 coreconfigitem(
2311 2317 b'web',
2312 2318 b'allowbz2',
2313 2319 default=False,
2314 2320 )
2315 2321 coreconfigitem(
2316 2322 b'web',
2317 2323 b'allowgz',
2318 2324 default=False,
2319 2325 )
2320 2326 coreconfigitem(
2321 2327 b'web',
2322 2328 b'allow-pull',
2323 2329 alias=[(b'web', b'allowpull')],
2324 2330 default=True,
2325 2331 )
2326 2332 coreconfigitem(
2327 2333 b'web',
2328 2334 b'allow-push',
2329 2335 alias=[(b'web', b'allow_push')],
2330 2336 default=list,
2331 2337 )
2332 2338 coreconfigitem(
2333 2339 b'web',
2334 2340 b'allowzip',
2335 2341 default=False,
2336 2342 )
2337 2343 coreconfigitem(
2338 2344 b'web',
2339 2345 b'archivesubrepos',
2340 2346 default=False,
2341 2347 )
2342 2348 coreconfigitem(
2343 2349 b'web',
2344 2350 b'cache',
2345 2351 default=True,
2346 2352 )
2347 2353 coreconfigitem(
2348 2354 b'web',
2349 2355 b'comparisoncontext',
2350 2356 default=5,
2351 2357 )
2352 2358 coreconfigitem(
2353 2359 b'web',
2354 2360 b'contact',
2355 2361 default=None,
2356 2362 )
2357 2363 coreconfigitem(
2358 2364 b'web',
2359 2365 b'deny_push',
2360 2366 default=list,
2361 2367 )
2362 2368 coreconfigitem(
2363 2369 b'web',
2364 2370 b'guessmime',
2365 2371 default=False,
2366 2372 )
2367 2373 coreconfigitem(
2368 2374 b'web',
2369 2375 b'hidden',
2370 2376 default=False,
2371 2377 )
2372 2378 coreconfigitem(
2373 2379 b'web',
2374 2380 b'labels',
2375 2381 default=list,
2376 2382 )
2377 2383 coreconfigitem(
2378 2384 b'web',
2379 2385 b'logoimg',
2380 2386 default=b'hglogo.png',
2381 2387 )
2382 2388 coreconfigitem(
2383 2389 b'web',
2384 2390 b'logourl',
2385 2391 default=b'https://mercurial-scm.org/',
2386 2392 )
2387 2393 coreconfigitem(
2388 2394 b'web',
2389 2395 b'accesslog',
2390 2396 default=b'-',
2391 2397 )
2392 2398 coreconfigitem(
2393 2399 b'web',
2394 2400 b'address',
2395 2401 default=b'',
2396 2402 )
2397 2403 coreconfigitem(
2398 2404 b'web',
2399 2405 b'allow-archive',
2400 2406 alias=[(b'web', b'allow_archive')],
2401 2407 default=list,
2402 2408 )
2403 2409 coreconfigitem(
2404 2410 b'web',
2405 2411 b'allow_read',
2406 2412 default=list,
2407 2413 )
2408 2414 coreconfigitem(
2409 2415 b'web',
2410 2416 b'baseurl',
2411 2417 default=None,
2412 2418 )
2413 2419 coreconfigitem(
2414 2420 b'web',
2415 2421 b'cacerts',
2416 2422 default=None,
2417 2423 )
2418 2424 coreconfigitem(
2419 2425 b'web',
2420 2426 b'certificate',
2421 2427 default=None,
2422 2428 )
2423 2429 coreconfigitem(
2424 2430 b'web',
2425 2431 b'collapse',
2426 2432 default=False,
2427 2433 )
2428 2434 coreconfigitem(
2429 2435 b'web',
2430 2436 b'csp',
2431 2437 default=None,
2432 2438 )
2433 2439 coreconfigitem(
2434 2440 b'web',
2435 2441 b'deny_read',
2436 2442 default=list,
2437 2443 )
2438 2444 coreconfigitem(
2439 2445 b'web',
2440 2446 b'descend',
2441 2447 default=True,
2442 2448 )
2443 2449 coreconfigitem(
2444 2450 b'web',
2445 2451 b'description',
2446 2452 default=b"",
2447 2453 )
2448 2454 coreconfigitem(
2449 2455 b'web',
2450 2456 b'encoding',
2451 2457 default=lambda: encoding.encoding,
2452 2458 )
2453 2459 coreconfigitem(
2454 2460 b'web',
2455 2461 b'errorlog',
2456 2462 default=b'-',
2457 2463 )
2458 2464 coreconfigitem(
2459 2465 b'web',
2460 2466 b'ipv6',
2461 2467 default=False,
2462 2468 )
2463 2469 coreconfigitem(
2464 2470 b'web',
2465 2471 b'maxchanges',
2466 2472 default=10,
2467 2473 )
2468 2474 coreconfigitem(
2469 2475 b'web',
2470 2476 b'maxfiles',
2471 2477 default=10,
2472 2478 )
2473 2479 coreconfigitem(
2474 2480 b'web',
2475 2481 b'maxshortchanges',
2476 2482 default=60,
2477 2483 )
2478 2484 coreconfigitem(
2479 2485 b'web',
2480 2486 b'motd',
2481 2487 default=b'',
2482 2488 )
2483 2489 coreconfigitem(
2484 2490 b'web',
2485 2491 b'name',
2486 2492 default=dynamicdefault,
2487 2493 )
2488 2494 coreconfigitem(
2489 2495 b'web',
2490 2496 b'port',
2491 2497 default=8000,
2492 2498 )
2493 2499 coreconfigitem(
2494 2500 b'web',
2495 2501 b'prefix',
2496 2502 default=b'',
2497 2503 )
2498 2504 coreconfigitem(
2499 2505 b'web',
2500 2506 b'push_ssl',
2501 2507 default=True,
2502 2508 )
2503 2509 coreconfigitem(
2504 2510 b'web',
2505 2511 b'refreshinterval',
2506 2512 default=20,
2507 2513 )
2508 2514 coreconfigitem(
2509 2515 b'web',
2510 2516 b'server-header',
2511 2517 default=None,
2512 2518 )
2513 2519 coreconfigitem(
2514 2520 b'web',
2515 2521 b'static',
2516 2522 default=None,
2517 2523 )
2518 2524 coreconfigitem(
2519 2525 b'web',
2520 2526 b'staticurl',
2521 2527 default=None,
2522 2528 )
2523 2529 coreconfigitem(
2524 2530 b'web',
2525 2531 b'stripes',
2526 2532 default=1,
2527 2533 )
2528 2534 coreconfigitem(
2529 2535 b'web',
2530 2536 b'style',
2531 2537 default=b'paper',
2532 2538 )
2533 2539 coreconfigitem(
2534 2540 b'web',
2535 2541 b'templates',
2536 2542 default=None,
2537 2543 )
2538 2544 coreconfigitem(
2539 2545 b'web',
2540 2546 b'view',
2541 2547 default=b'served',
2542 2548 experimental=True,
2543 2549 )
2544 2550 coreconfigitem(
2545 2551 b'worker',
2546 2552 b'backgroundclose',
2547 2553 default=dynamicdefault,
2548 2554 )
2549 2555 # Windows defaults to a limit of 512 open files. A buffer of 128
2550 2556 # should give us enough headway.
2551 2557 coreconfigitem(
2552 2558 b'worker',
2553 2559 b'backgroundclosemaxqueue',
2554 2560 default=384,
2555 2561 )
2556 2562 coreconfigitem(
2557 2563 b'worker',
2558 2564 b'backgroundcloseminfilecount',
2559 2565 default=2048,
2560 2566 )
2561 2567 coreconfigitem(
2562 2568 b'worker',
2563 2569 b'backgroundclosethreadcount',
2564 2570 default=4,
2565 2571 )
2566 2572 coreconfigitem(
2567 2573 b'worker',
2568 2574 b'enabled',
2569 2575 default=True,
2570 2576 )
2571 2577 coreconfigitem(
2572 2578 b'worker',
2573 2579 b'numcpus',
2574 2580 default=None,
2575 2581 )
2576 2582
2577 2583 # Rebase related configuration moved to core because other extension are doing
2578 2584 # strange things. For example, shelve import the extensions to reuse some bit
2579 2585 # without formally loading it.
2580 2586 coreconfigitem(
2581 2587 b'commands',
2582 2588 b'rebase.requiredest',
2583 2589 default=False,
2584 2590 )
2585 2591 coreconfigitem(
2586 2592 b'experimental',
2587 2593 b'rebaseskipobsolete',
2588 2594 default=True,
2589 2595 )
2590 2596 coreconfigitem(
2591 2597 b'rebase',
2592 2598 b'singletransaction',
2593 2599 default=False,
2594 2600 )
2595 2601 coreconfigitem(
2596 2602 b'rebase',
2597 2603 b'experimental.inmemory',
2598 2604 default=False,
2599 2605 )
@@ -1,1230 +1,1238 b''
1 1 # coding: utf8
2 2 # copies.py - copy detection for Mercurial
3 3 #
4 4 # Copyright 2008 Matt Mackall <mpm@selenic.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import collections
12 12 import os
13 13
14 14 from .i18n import _
15 15 from .node import (
16 16 nullid,
17 17 nullrev,
18 18 )
19 19
20 20 from . import (
21 21 match as matchmod,
22 22 pathutil,
23 23 policy,
24 24 pycompat,
25 25 util,
26 26 )
27 27
28 28
29 29 from .utils import stringutil
30 30
31 31 from .revlogutils import (
32 32 flagutil,
33 33 sidedata as sidedatamod,
34 34 )
35 35
36 36 rustmod = policy.importrust("copy_tracing")
37 37
38 38
39 39 def _filter(src, dst, t):
40 40 """filters out invalid copies after chaining"""
41 41
42 42 # When _chain()'ing copies in 'a' (from 'src' via some other commit 'mid')
43 43 # with copies in 'b' (from 'mid' to 'dst'), we can get the different cases
44 44 # in the following table (not including trivial cases). For example, case 6
45 45 # is where a file existed in 'src' and remained under that name in 'mid' and
46 46 # then was renamed between 'mid' and 'dst'.
47 47 #
48 48 # case src mid dst result
49 49 # 1 x y - -
50 50 # 2 x y y x->y
51 51 # 3 x y x -
52 52 # 4 x y z x->z
53 53 # 5 - x y -
54 54 # 6 x x y x->y
55 55 #
56 56 # _chain() takes care of chaining the copies in 'a' and 'b', but it
57 57 # cannot tell the difference between cases 1 and 2, between 3 and 4, or
58 58 # between 5 and 6, so it includes all cases in its result.
59 59 # Cases 1, 3, and 5 are then removed by _filter().
60 60
61 61 for k, v in list(t.items()):
62 62 if k == v: # case 3
63 63 del t[k]
64 64 elif v not in src: # case 5
65 65 # remove copies from files that didn't exist
66 66 del t[k]
67 67 elif k not in dst: # case 1
68 68 # remove copies to files that were then removed
69 69 del t[k]
70 70
71 71
72 72 def _chain(prefix, suffix):
73 73 """chain two sets of copies 'prefix' and 'suffix'"""
74 74 result = prefix.copy()
75 75 for key, value in pycompat.iteritems(suffix):
76 76 result[key] = prefix.get(value, value)
77 77 return result
78 78
79 79
80 80 def _tracefile(fctx, am, basemf):
81 81 """return file context that is the ancestor of fctx present in ancestor
82 82 manifest am
83 83
84 84 Note: we used to try and stop after a given limit, however checking if that
85 85 limit is reached turned out to be very expensive. we are better off
86 86 disabling that feature."""
87 87
88 88 for f in fctx.ancestors():
89 89 path = f.path()
90 90 if am.get(path, None) == f.filenode():
91 91 return path
92 92 if basemf and basemf.get(path, None) == f.filenode():
93 93 return path
94 94
95 95
96 96 def _dirstatecopies(repo, match=None):
97 97 ds = repo.dirstate
98 98 c = ds.copies().copy()
99 99 for k in list(c):
100 100 if ds[k] not in b'anm' or (match and not match(k)):
101 101 del c[k]
102 102 return c
103 103
104 104
105 105 def _computeforwardmissing(a, b, match=None):
106 106 """Computes which files are in b but not a.
107 107 This is its own function so extensions can easily wrap this call to see what
108 108 files _forwardcopies is about to process.
109 109 """
110 110 ma = a.manifest()
111 111 mb = b.manifest()
112 112 return mb.filesnotin(ma, match=match)
113 113
114 114
115 115 def usechangesetcentricalgo(repo):
116 116 """Checks if we should use changeset-centric copy algorithms"""
117 117 if repo.filecopiesmode == b'changeset-sidedata':
118 118 return True
119 119 readfrom = repo.ui.config(b'experimental', b'copies.read-from')
120 120 changesetsource = (b'changeset-only', b'compatibility')
121 121 return readfrom in changesetsource
122 122
123 123
124 124 def _committedforwardcopies(a, b, base, match):
125 125 """Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
126 126 # files might have to be traced back to the fctx parent of the last
127 127 # one-side-only changeset, but not further back than that
128 128 repo = a._repo
129 129
130 130 if usechangesetcentricalgo(repo):
131 131 return _changesetforwardcopies(a, b, match)
132 132
133 133 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
134 134 dbg = repo.ui.debug
135 135 if debug:
136 136 dbg(b'debug.copies: looking into rename from %s to %s\n' % (a, b))
137 137 am = a.manifest()
138 138 basemf = None if base is None else base.manifest()
139 139
140 140 # find where new files came from
141 141 # we currently don't try to find where old files went, too expensive
142 142 # this means we can miss a case like 'hg rm b; hg cp a b'
143 143 cm = {}
144 144
145 145 # Computing the forward missing is quite expensive on large manifests, since
146 146 # it compares the entire manifests. We can optimize it in the common use
147 147 # case of computing what copies are in a commit versus its parent (like
148 148 # during a rebase or histedit). Note, we exclude merge commits from this
149 149 # optimization, since the ctx.files() for a merge commit is not correct for
150 150 # this comparison.
151 151 forwardmissingmatch = match
152 152 if b.p1() == a and b.p2().node() == nullid:
153 153 filesmatcher = matchmod.exact(b.files())
154 154 forwardmissingmatch = matchmod.intersectmatchers(match, filesmatcher)
155 if repo.ui.configbool(b'devel', b'copy-tracing.trace-all-files'):
156 missing = list(b.walk(match))
157 # _computeforwardmissing(a, b, match=forwardmissingmatch)
158 if debug:
159 dbg(b'debug.copies: searching all files: %d\n' % len(missing))
160 else:
155 161 missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
162 if debug:
163 dbg(
164 b'debug.copies: missing files to search: %d\n'
165 % len(missing)
166 )
156 167
157 168 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
158 169
159 if debug:
160 dbg(b'debug.copies: missing files to search: %d\n' % len(missing))
161
162 170 for f in sorted(missing):
163 171 if debug:
164 172 dbg(b'debug.copies: tracing file: %s\n' % f)
165 173 fctx = b[f]
166 174 fctx._ancestrycontext = ancestrycontext
167 175
168 176 if debug:
169 177 start = util.timer()
170 178 opath = _tracefile(fctx, am, basemf)
171 179 if opath:
172 180 if debug:
173 181 dbg(b'debug.copies: rename of: %s\n' % opath)
174 182 cm[f] = opath
175 183 if debug:
176 184 dbg(
177 185 b'debug.copies: time: %f seconds\n'
178 186 % (util.timer() - start)
179 187 )
180 188 return cm
181 189
182 190
183 191 def _revinfo_getter(repo, match):
184 192 """returns a function that returns the following data given a <rev>"
185 193
186 194 * p1: revision number of first parent
187 195 * p2: revision number of first parent
188 196 * changes: a ChangingFiles object
189 197 """
190 198 cl = repo.changelog
191 199 parents = cl.parentrevs
192 200 flags = cl.flags
193 201
194 202 HASCOPIESINFO = flagutil.REVIDX_HASCOPIESINFO
195 203
196 204 changelogrevision = cl.changelogrevision
197 205
198 206 if rustmod is not None:
199 207
200 208 def revinfo(rev):
201 209 p1, p2 = parents(rev)
202 210 if flags(rev) & HASCOPIESINFO:
203 211 raw = changelogrevision(rev)._sidedata.get(sidedatamod.SD_FILES)
204 212 else:
205 213 raw = None
206 214 return (p1, p2, raw)
207 215
208 216 else:
209 217
210 218 def revinfo(rev):
211 219 p1, p2 = parents(rev)
212 220 if flags(rev) & HASCOPIESINFO:
213 221 changes = changelogrevision(rev).changes
214 222 else:
215 223 changes = None
216 224 return (p1, p2, changes)
217 225
218 226 return revinfo
219 227
220 228
221 229 def cached_is_ancestor(is_ancestor):
222 230 """return a cached version of is_ancestor"""
223 231 cache = {}
224 232
225 233 def _is_ancestor(anc, desc):
226 234 if anc > desc:
227 235 return False
228 236 elif anc == desc:
229 237 return True
230 238 key = (anc, desc)
231 239 ret = cache.get(key)
232 240 if ret is None:
233 241 ret = cache[key] = is_ancestor(anc, desc)
234 242 return ret
235 243
236 244 return _is_ancestor
237 245
238 246
239 247 def _changesetforwardcopies(a, b, match):
240 248 if a.rev() in (nullrev, b.rev()):
241 249 return {}
242 250
243 251 repo = a.repo().unfiltered()
244 252 children = {}
245 253
246 254 cl = repo.changelog
247 255 isancestor = cl.isancestorrev
248 256
249 257 # To track rename from "A" to B, we need to gather all parent β†’ children
250 258 # edges that are contains in `::B` but not in `::A`.
251 259 #
252 260 #
253 261 # To do so, we need to gather all revisions exclusiveΒΉ to "B" (ieΒΉ: `::b -
254 262 # ::a`) and also all the "roots point", ie the parents of the exclusive set
255 263 # that belong to ::a. These are exactly all the revisions needed to express
256 264 # the parent β†’ children we need to combine.
257 265 #
258 266 # [1] actually, we need to gather all the edges within `(::a)::b`, ie:
259 267 # excluding paths that leads to roots that are not ancestors of `a`. We
260 268 # keep this out of the explanation because it is hard enough without this special case..
261 269
262 270 parents = cl._uncheckedparentrevs
263 271 graph_roots = (nullrev, nullrev)
264 272
265 273 ancestors = cl.ancestors([a.rev()], inclusive=True)
266 274 revs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()])
267 275 roots = set()
268 276 has_graph_roots = False
269 277
270 278 # iterate over `only(B, A)`
271 279 for r in revs:
272 280 ps = parents(r)
273 281 if ps == graph_roots:
274 282 has_graph_roots = True
275 283 else:
276 284 p1, p2 = ps
277 285
278 286 # find all the "root points" (see larger comment above)
279 287 if p1 != nullrev and p1 in ancestors:
280 288 roots.add(p1)
281 289 if p2 != nullrev and p2 in ancestors:
282 290 roots.add(p2)
283 291 if not roots:
284 292 # no common revision to track copies from
285 293 return {}
286 294 if has_graph_roots:
287 295 # this deal with the special case mentionned in the [1] footnotes. We
288 296 # must filter out revisions that leads to non-common graphroots.
289 297 roots = list(roots)
290 298 m = min(roots)
291 299 h = [b.rev()]
292 300 roots_to_head = cl.reachableroots(m, h, roots, includepath=True)
293 301 roots_to_head = set(roots_to_head)
294 302 revs = [r for r in revs if r in roots_to_head]
295 303
296 304 if repo.filecopiesmode == b'changeset-sidedata':
297 305 # When using side-data, we will process the edges "from" the children.
298 306 # We iterate over the childre, gathering previous collected data for
299 307 # the parents. Do know when the parents data is no longer necessary, we
300 308 # keep a counter of how many children each revision has.
301 309 #
302 310 # An interresting property of `children_count` is that it only contains
303 311 # revision that will be relevant for a edge of the graph. So if a
304 312 # children has parent not in `children_count`, that edges should not be
305 313 # processed.
306 314 children_count = dict((r, 0) for r in roots)
307 315 for r in revs:
308 316 for p in cl.parentrevs(r):
309 317 if p == nullrev:
310 318 continue
311 319 children_count[r] = 0
312 320 if p in children_count:
313 321 children_count[p] += 1
314 322 revinfo = _revinfo_getter(repo, match)
315 323 return _combine_changeset_copies(
316 324 revs, children_count, b.rev(), revinfo, match, isancestor
317 325 )
318 326 else:
319 327 # When not using side-data, we will process the edges "from" the parent.
320 328 # so we need a full mapping of the parent -> children relation.
321 329 children = dict((r, []) for r in roots)
322 330 for r in revs:
323 331 for p in cl.parentrevs(r):
324 332 if p == nullrev:
325 333 continue
326 334 children[r] = []
327 335 if p in children:
328 336 children[p].append(r)
329 337 x = revs.pop()
330 338 assert x == b.rev()
331 339 revs.extend(roots)
332 340 revs.sort()
333 341
334 342 revinfo = _revinfo_getter_extra(repo)
335 343 return _combine_changeset_copies_extra(
336 344 revs, children, b.rev(), revinfo, match, isancestor
337 345 )
338 346
339 347
340 348 def _combine_changeset_copies(
341 349 revs, children_count, targetrev, revinfo, match, isancestor
342 350 ):
343 351 """combine the copies information for each item of iterrevs
344 352
345 353 revs: sorted iterable of revision to visit
346 354 children_count: a {parent: <number-of-relevant-children>} mapping.
347 355 targetrev: the final copies destination revision (not in iterrevs)
348 356 revinfo(rev): a function that return (p1, p2, p1copies, p2copies, removed)
349 357 match: a matcher
350 358
351 359 It returns the aggregated copies information for `targetrev`.
352 360 """
353 361
354 362 alwaysmatch = match.always()
355 363
356 364 if rustmod is not None:
357 365 final_copies = rustmod.combine_changeset_copies(
358 366 list(revs), children_count, targetrev, revinfo, isancestor
359 367 )
360 368 else:
361 369 isancestor = cached_is_ancestor(isancestor)
362 370
363 371 all_copies = {}
364 372 # iterate over all the "children" side of copy tracing "edge"
365 373 for current_rev in revs:
366 374 p1, p2, changes = revinfo(current_rev)
367 375 current_copies = None
368 376 # iterate over all parents to chain the existing data with the
369 377 # data from the parent β†’ child edge.
370 378 for parent, parent_rev in ((1, p1), (2, p2)):
371 379 if parent_rev == nullrev:
372 380 continue
373 381 remaining_children = children_count.get(parent_rev)
374 382 if remaining_children is None:
375 383 continue
376 384 remaining_children -= 1
377 385 children_count[parent_rev] = remaining_children
378 386 if remaining_children:
379 387 copies = all_copies.get(parent_rev, None)
380 388 else:
381 389 copies = all_copies.pop(parent_rev, None)
382 390
383 391 if copies is None:
384 392 # this is a root
385 393 newcopies = copies = {}
386 394 elif remaining_children:
387 395 newcopies = copies.copy()
388 396 else:
389 397 newcopies = copies
390 398 # chain the data in the edge with the existing data
391 399 if changes is not None:
392 400 childcopies = {}
393 401 if parent == 1:
394 402 childcopies = changes.copied_from_p1
395 403 elif parent == 2:
396 404 childcopies = changes.copied_from_p2
397 405
398 406 if childcopies:
399 407 newcopies = copies.copy()
400 408 for dest, source in pycompat.iteritems(childcopies):
401 409 prev = copies.get(source)
402 410 if prev is not None and prev[1] is not None:
403 411 source = prev[1]
404 412 newcopies[dest] = (current_rev, source)
405 413 assert newcopies is not copies
406 414 if changes.removed:
407 415 for f in changes.removed:
408 416 if f in newcopies:
409 417 if newcopies is copies:
410 418 # copy on write to avoid affecting potential other
411 419 # branches. when there are no other branches, this
412 420 # could be avoided.
413 421 newcopies = copies.copy()
414 422 newcopies[f] = (current_rev, None)
415 423 # check potential need to combine the data from another parent (for
416 424 # that child). See comment below for details.
417 425 if current_copies is None:
418 426 current_copies = newcopies
419 427 else:
420 428 # we are the second parent to work on c, we need to merge our
421 429 # work with the other.
422 430 #
423 431 # In case of conflict, parent 1 take precedence over parent 2.
424 432 # This is an arbitrary choice made anew when implementing
425 433 # changeset based copies. It was made without regards with
426 434 # potential filelog related behavior.
427 435 assert parent == 2
428 436 current_copies = _merge_copies_dict(
429 437 newcopies, current_copies, isancestor, changes
430 438 )
431 439 all_copies[current_rev] = current_copies
432 440
433 441 # filter out internal details and return a {dest: source mapping}
434 442 final_copies = {}
435 443 for dest, (tt, source) in all_copies[targetrev].items():
436 444 if source is not None:
437 445 final_copies[dest] = source
438 446 if not alwaysmatch:
439 447 for filename in list(final_copies.keys()):
440 448 if not match(filename):
441 449 del final_copies[filename]
442 450 return final_copies
443 451
444 452
445 453 # constant to decide which side to pick with _merge_copies_dict
446 454 PICK_MINOR = 0
447 455 PICK_MAJOR = 1
448 456 PICK_EITHER = 2
449 457
450 458
451 459 def _merge_copies_dict(minor, major, isancestor, changes):
452 460 """merge two copies-mapping together, minor and major
453 461
454 462 In case of conflict, value from "major" will be picked.
455 463
456 464 - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an
457 465 ancestors of `high_rev`,
458 466
459 467 - `ismerged(path)`: callable return True if `path` have been merged in the
460 468 current revision,
461 469
462 470 return the resulting dict (in practice, the "minor" object, updated)
463 471 """
464 472 for dest, value in major.items():
465 473 other = minor.get(dest)
466 474 if other is None:
467 475 minor[dest] = value
468 476 else:
469 477 pick = _compare_values(changes, isancestor, dest, other, value)
470 478 if pick == PICK_MAJOR:
471 479 minor[dest] = value
472 480 return minor
473 481
474 482
475 483 def _compare_values(changes, isancestor, dest, minor, major):
476 484 """compare two value within a _merge_copies_dict loop iteration"""
477 485 major_tt, major_value = major
478 486 minor_tt, minor_value = minor
479 487
480 488 # evacuate some simple case first:
481 489 if major_tt == minor_tt:
482 490 # if it comes from the same revision it must be the same value
483 491 assert major_value == minor_value
484 492 return PICK_EITHER
485 493 elif major[1] == minor[1]:
486 494 return PICK_EITHER
487 495
488 496 # actual merging needed: content from "major" wins, unless it is older than
489 497 # the branch point or there is a merge
490 498 elif changes is not None and major[1] is None and dest in changes.salvaged:
491 499 return PICK_MINOR
492 500 elif changes is not None and minor[1] is None and dest in changes.salvaged:
493 501 return PICK_MAJOR
494 502 elif changes is not None and dest in changes.merged:
495 503 return PICK_MAJOR
496 504 elif not isancestor(major_tt, minor_tt):
497 505 if major[1] is not None:
498 506 return PICK_MAJOR
499 507 elif isancestor(minor_tt, major_tt):
500 508 return PICK_MAJOR
501 509 return PICK_MINOR
502 510
503 511
504 512 def _revinfo_getter_extra(repo):
505 513 """return a function that return multiple data given a <rev>"i
506 514
507 515 * p1: revision number of first parent
508 516 * p2: revision number of first parent
509 517 * p1copies: mapping of copies from p1
510 518 * p2copies: mapping of copies from p2
511 519 * removed: a list of removed files
512 520 * ismerged: a callback to know if file was merged in that revision
513 521 """
514 522 cl = repo.changelog
515 523 parents = cl.parentrevs
516 524
517 525 def get_ismerged(rev):
518 526 ctx = repo[rev]
519 527
520 528 def ismerged(path):
521 529 if path not in ctx.files():
522 530 return False
523 531 fctx = ctx[path]
524 532 parents = fctx._filelog.parents(fctx._filenode)
525 533 nb_parents = 0
526 534 for n in parents:
527 535 if n != nullid:
528 536 nb_parents += 1
529 537 return nb_parents >= 2
530 538
531 539 return ismerged
532 540
533 541 def revinfo(rev):
534 542 p1, p2 = parents(rev)
535 543 ctx = repo[rev]
536 544 p1copies, p2copies = ctx._copies
537 545 removed = ctx.filesremoved()
538 546 return p1, p2, p1copies, p2copies, removed, get_ismerged(rev)
539 547
540 548 return revinfo
541 549
542 550
543 551 def _combine_changeset_copies_extra(
544 552 revs, children, targetrev, revinfo, match, isancestor
545 553 ):
546 554 """version of `_combine_changeset_copies` that works with the Google
547 555 specific "extra" based storage for copy information"""
548 556 all_copies = {}
549 557 alwaysmatch = match.always()
550 558 for r in revs:
551 559 copies = all_copies.pop(r, None)
552 560 if copies is None:
553 561 # this is a root
554 562 copies = {}
555 563 for i, c in enumerate(children[r]):
556 564 p1, p2, p1copies, p2copies, removed, ismerged = revinfo(c)
557 565 if r == p1:
558 566 parent = 1
559 567 childcopies = p1copies
560 568 else:
561 569 assert r == p2
562 570 parent = 2
563 571 childcopies = p2copies
564 572 if not alwaysmatch:
565 573 childcopies = {
566 574 dst: src for dst, src in childcopies.items() if match(dst)
567 575 }
568 576 newcopies = copies
569 577 if childcopies:
570 578 newcopies = copies.copy()
571 579 for dest, source in pycompat.iteritems(childcopies):
572 580 prev = copies.get(source)
573 581 if prev is not None and prev[1] is not None:
574 582 source = prev[1]
575 583 newcopies[dest] = (c, source)
576 584 assert newcopies is not copies
577 585 for f in removed:
578 586 if f in newcopies:
579 587 if newcopies is copies:
580 588 # copy on write to avoid affecting potential other
581 589 # branches. when there are no other branches, this
582 590 # could be avoided.
583 591 newcopies = copies.copy()
584 592 newcopies[f] = (c, None)
585 593 othercopies = all_copies.get(c)
586 594 if othercopies is None:
587 595 all_copies[c] = newcopies
588 596 else:
589 597 # we are the second parent to work on c, we need to merge our
590 598 # work with the other.
591 599 #
592 600 # In case of conflict, parent 1 take precedence over parent 2.
593 601 # This is an arbitrary choice made anew when implementing
594 602 # changeset based copies. It was made without regards with
595 603 # potential filelog related behavior.
596 604 if parent == 1:
597 605 _merge_copies_dict_extra(
598 606 othercopies, newcopies, isancestor, ismerged
599 607 )
600 608 else:
601 609 _merge_copies_dict_extra(
602 610 newcopies, othercopies, isancestor, ismerged
603 611 )
604 612 all_copies[c] = newcopies
605 613
606 614 final_copies = {}
607 615 for dest, (tt, source) in all_copies[targetrev].items():
608 616 if source is not None:
609 617 final_copies[dest] = source
610 618 return final_copies
611 619
612 620
613 621 def _merge_copies_dict_extra(minor, major, isancestor, ismerged):
614 622 """version of `_merge_copies_dict` that works with the Google
615 623 specific "extra" based storage for copy information"""
616 624 for dest, value in major.items():
617 625 other = minor.get(dest)
618 626 if other is None:
619 627 minor[dest] = value
620 628 else:
621 629 new_tt = value[0]
622 630 other_tt = other[0]
623 631 if value[1] == other[1]:
624 632 continue
625 633 # content from "major" wins, unless it is older
626 634 # than the branch point or there is a merge
627 635 if (
628 636 new_tt == other_tt
629 637 or not isancestor(new_tt, other_tt)
630 638 or ismerged(dest)
631 639 ):
632 640 minor[dest] = value
633 641
634 642
635 643 def _forwardcopies(a, b, base=None, match=None):
636 644 """find {dst@b: src@a} copy mapping where a is an ancestor of b"""
637 645
638 646 if base is None:
639 647 base = a
640 648 match = a.repo().narrowmatch(match)
641 649 # check for working copy
642 650 if b.rev() is None:
643 651 cm = _committedforwardcopies(a, b.p1(), base, match)
644 652 # combine copies from dirstate if necessary
645 653 copies = _chain(cm, _dirstatecopies(b._repo, match))
646 654 else:
647 655 copies = _committedforwardcopies(a, b, base, match)
648 656 return copies
649 657
650 658
651 659 def _backwardrenames(a, b, match):
652 660 if a._repo.ui.config(b'experimental', b'copytrace') == b'off':
653 661 return {}
654 662
655 663 # Even though we're not taking copies into account, 1:n rename situations
656 664 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
657 665 # arbitrarily pick one of the renames.
658 666 # We don't want to pass in "match" here, since that would filter
659 667 # the destination by it. Since we're reversing the copies, we want
660 668 # to filter the source instead.
661 669 f = _forwardcopies(b, a)
662 670 r = {}
663 671 for k, v in sorted(pycompat.iteritems(f)):
664 672 if match and not match(v):
665 673 continue
666 674 # remove copies
667 675 if v in a:
668 676 continue
669 677 r[v] = k
670 678 return r
671 679
672 680
673 681 def pathcopies(x, y, match=None):
674 682 """find {dst@y: src@x} copy mapping for directed compare"""
675 683 repo = x._repo
676 684 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
677 685 if debug:
678 686 repo.ui.debug(
679 687 b'debug.copies: searching copies from %s to %s\n' % (x, y)
680 688 )
681 689 if x == y or not x or not y:
682 690 return {}
683 691 if y.rev() is None and x == y.p1():
684 692 if debug:
685 693 repo.ui.debug(b'debug.copies: search mode: dirstate\n')
686 694 # short-circuit to avoid issues with merge states
687 695 return _dirstatecopies(repo, match)
688 696 a = y.ancestor(x)
689 697 if a == x:
690 698 if debug:
691 699 repo.ui.debug(b'debug.copies: search mode: forward\n')
692 700 copies = _forwardcopies(x, y, match=match)
693 701 elif a == y:
694 702 if debug:
695 703 repo.ui.debug(b'debug.copies: search mode: backward\n')
696 704 copies = _backwardrenames(x, y, match=match)
697 705 else:
698 706 if debug:
699 707 repo.ui.debug(b'debug.copies: search mode: combined\n')
700 708 base = None
701 709 if a.rev() != nullrev:
702 710 base = x
703 711 copies = _chain(
704 712 _backwardrenames(x, a, match=match),
705 713 _forwardcopies(a, y, base, match=match),
706 714 )
707 715 _filter(x, y, copies)
708 716 return copies
709 717
710 718
711 719 def mergecopies(repo, c1, c2, base):
712 720 """
713 721 Finds moves and copies between context c1 and c2 that are relevant for
714 722 merging. 'base' will be used as the merge base.
715 723
716 724 Copytracing is used in commands like rebase, merge, unshelve, etc to merge
717 725 files that were moved/ copied in one merge parent and modified in another.
718 726 For example:
719 727
720 728 o ---> 4 another commit
721 729 |
722 730 | o ---> 3 commit that modifies a.txt
723 731 | /
724 732 o / ---> 2 commit that moves a.txt to b.txt
725 733 |/
726 734 o ---> 1 merge base
727 735
728 736 If we try to rebase revision 3 on revision 4, since there is no a.txt in
729 737 revision 4, and if user have copytrace disabled, we prints the following
730 738 message:
731 739
732 740 ```other changed <file> which local deleted```
733 741
734 742 Returns a tuple where:
735 743
736 744 "branch_copies" an instance of branch_copies.
737 745
738 746 "diverge" is a mapping of source name -> list of destination names
739 747 for divergent renames.
740 748
741 749 This function calls different copytracing algorithms based on config.
742 750 """
743 751 # avoid silly behavior for update from empty dir
744 752 if not c1 or not c2 or c1 == c2:
745 753 return branch_copies(), branch_copies(), {}
746 754
747 755 narrowmatch = c1.repo().narrowmatch()
748 756
749 757 # avoid silly behavior for parent -> working dir
750 758 if c2.node() is None and c1.node() == repo.dirstate.p1():
751 759 return (
752 760 branch_copies(_dirstatecopies(repo, narrowmatch)),
753 761 branch_copies(),
754 762 {},
755 763 )
756 764
757 765 copytracing = repo.ui.config(b'experimental', b'copytrace')
758 766 if stringutil.parsebool(copytracing) is False:
759 767 # stringutil.parsebool() returns None when it is unable to parse the
760 768 # value, so we should rely on making sure copytracing is on such cases
761 769 return branch_copies(), branch_copies(), {}
762 770
763 771 if usechangesetcentricalgo(repo):
764 772 # The heuristics don't make sense when we need changeset-centric algos
765 773 return _fullcopytracing(repo, c1, c2, base)
766 774
767 775 # Copy trace disabling is explicitly below the node == p1 logic above
768 776 # because the logic above is required for a simple copy to be kept across a
769 777 # rebase.
770 778 if copytracing == b'heuristics':
771 779 # Do full copytracing if only non-public revisions are involved as
772 780 # that will be fast enough and will also cover the copies which could
773 781 # be missed by heuristics
774 782 if _isfullcopytraceable(repo, c1, base):
775 783 return _fullcopytracing(repo, c1, c2, base)
776 784 return _heuristicscopytracing(repo, c1, c2, base)
777 785 else:
778 786 return _fullcopytracing(repo, c1, c2, base)
779 787
780 788
781 789 def _isfullcopytraceable(repo, c1, base):
782 790 """Checks that if base, source and destination are all no-public branches,
783 791 if yes let's use the full copytrace algorithm for increased capabilities
784 792 since it will be fast enough.
785 793
786 794 `experimental.copytrace.sourcecommitlimit` can be used to set a limit for
787 795 number of changesets from c1 to base such that if number of changesets are
788 796 more than the limit, full copytracing algorithm won't be used.
789 797 """
790 798 if c1.rev() is None:
791 799 c1 = c1.p1()
792 800 if c1.mutable() and base.mutable():
793 801 sourcecommitlimit = repo.ui.configint(
794 802 b'experimental', b'copytrace.sourcecommitlimit'
795 803 )
796 804 commits = len(repo.revs(b'%d::%d', base.rev(), c1.rev()))
797 805 return commits < sourcecommitlimit
798 806 return False
799 807
800 808
801 809 def _checksinglesidecopies(
802 810 src, dsts1, m1, m2, mb, c2, base, copy, renamedelete
803 811 ):
804 812 if src not in m2:
805 813 # deleted on side 2
806 814 if src not in m1:
807 815 # renamed on side 1, deleted on side 2
808 816 renamedelete[src] = dsts1
809 817 elif src not in mb:
810 818 # Work around the "short-circuit to avoid issues with merge states"
811 819 # thing in pathcopies(): pathcopies(x, y) can return a copy where the
812 820 # destination doesn't exist in y.
813 821 pass
814 822 elif mb[src] != m2[src] and not _related(c2[src], base[src]):
815 823 return
816 824 elif mb[src] != m2[src] or mb.flags(src) != m2.flags(src):
817 825 # modified on side 2
818 826 for dst in dsts1:
819 827 copy[dst] = src
820 828
821 829
822 830 class branch_copies(object):
823 831 """Information about copies made on one side of a merge/graft.
824 832
825 833 "copy" is a mapping from destination name -> source name,
826 834 where source is in c1 and destination is in c2 or vice-versa.
827 835
828 836 "movewithdir" is a mapping from source name -> destination name,
829 837 where the file at source present in one context but not the other
830 838 needs to be moved to destination by the merge process, because the
831 839 other context moved the directory it is in.
832 840
833 841 "renamedelete" is a mapping of source name -> list of destination
834 842 names for files deleted in c1 that were renamed in c2 or vice-versa.
835 843
836 844 "dirmove" is a mapping of detected source dir -> destination dir renames.
837 845 This is needed for handling changes to new files previously grafted into
838 846 renamed directories.
839 847 """
840 848
841 849 def __init__(
842 850 self, copy=None, renamedelete=None, dirmove=None, movewithdir=None
843 851 ):
844 852 self.copy = {} if copy is None else copy
845 853 self.renamedelete = {} if renamedelete is None else renamedelete
846 854 self.dirmove = {} if dirmove is None else dirmove
847 855 self.movewithdir = {} if movewithdir is None else movewithdir
848 856
849 857 def __repr__(self):
850 858 return '<branch_copies\n copy=%r\n renamedelete=%r\n dirmove=%r\n movewithdir=%r\n>' % (
851 859 self.copy,
852 860 self.renamedelete,
853 861 self.dirmove,
854 862 self.movewithdir,
855 863 )
856 864
857 865
858 866 def _fullcopytracing(repo, c1, c2, base):
859 867 """The full copytracing algorithm which finds all the new files that were
860 868 added from merge base up to the top commit and for each file it checks if
861 869 this file was copied from another file.
862 870
863 871 This is pretty slow when a lot of changesets are involved but will track all
864 872 the copies.
865 873 """
866 874 m1 = c1.manifest()
867 875 m2 = c2.manifest()
868 876 mb = base.manifest()
869 877
870 878 copies1 = pathcopies(base, c1)
871 879 copies2 = pathcopies(base, c2)
872 880
873 881 if not (copies1 or copies2):
874 882 return branch_copies(), branch_copies(), {}
875 883
876 884 inversecopies1 = {}
877 885 inversecopies2 = {}
878 886 for dst, src in copies1.items():
879 887 inversecopies1.setdefault(src, []).append(dst)
880 888 for dst, src in copies2.items():
881 889 inversecopies2.setdefault(src, []).append(dst)
882 890
883 891 copy1 = {}
884 892 copy2 = {}
885 893 diverge = {}
886 894 renamedelete1 = {}
887 895 renamedelete2 = {}
888 896 allsources = set(inversecopies1) | set(inversecopies2)
889 897 for src in allsources:
890 898 dsts1 = inversecopies1.get(src)
891 899 dsts2 = inversecopies2.get(src)
892 900 if dsts1 and dsts2:
893 901 # copied/renamed on both sides
894 902 if src not in m1 and src not in m2:
895 903 # renamed on both sides
896 904 dsts1 = set(dsts1)
897 905 dsts2 = set(dsts2)
898 906 # If there's some overlap in the rename destinations, we
899 907 # consider it not divergent. For example, if side 1 copies 'a'
900 908 # to 'b' and 'c' and deletes 'a', and side 2 copies 'a' to 'c'
901 909 # and 'd' and deletes 'a'.
902 910 if dsts1 & dsts2:
903 911 for dst in dsts1 & dsts2:
904 912 copy1[dst] = src
905 913 copy2[dst] = src
906 914 else:
907 915 diverge[src] = sorted(dsts1 | dsts2)
908 916 elif src in m1 and src in m2:
909 917 # copied on both sides
910 918 dsts1 = set(dsts1)
911 919 dsts2 = set(dsts2)
912 920 for dst in dsts1 & dsts2:
913 921 copy1[dst] = src
914 922 copy2[dst] = src
915 923 # TODO: Handle cases where it was renamed on one side and copied
916 924 # on the other side
917 925 elif dsts1:
918 926 # copied/renamed only on side 1
919 927 _checksinglesidecopies(
920 928 src, dsts1, m1, m2, mb, c2, base, copy1, renamedelete1
921 929 )
922 930 elif dsts2:
923 931 # copied/renamed only on side 2
924 932 _checksinglesidecopies(
925 933 src, dsts2, m2, m1, mb, c1, base, copy2, renamedelete2
926 934 )
927 935
928 936 # find interesting file sets from manifests
929 937 cache = []
930 938
931 939 def _get_addedfiles(idx):
932 940 if not cache:
933 941 addedinm1 = m1.filesnotin(mb, repo.narrowmatch())
934 942 addedinm2 = m2.filesnotin(mb, repo.narrowmatch())
935 943 u1 = sorted(addedinm1 - addedinm2)
936 944 u2 = sorted(addedinm2 - addedinm1)
937 945 cache.extend((u1, u2))
938 946 return cache[idx]
939 947
940 948 u1fn = lambda: _get_addedfiles(0)
941 949 u2fn = lambda: _get_addedfiles(1)
942 950 if repo.ui.debugflag:
943 951 u1 = u1fn()
944 952 u2 = u2fn()
945 953
946 954 header = b" unmatched files in %s"
947 955 if u1:
948 956 repo.ui.debug(
949 957 b"%s:\n %s\n" % (header % b'local', b"\n ".join(u1))
950 958 )
951 959 if u2:
952 960 repo.ui.debug(
953 961 b"%s:\n %s\n" % (header % b'other', b"\n ".join(u2))
954 962 )
955 963
956 964 renamedeleteset = set()
957 965 divergeset = set()
958 966 for dsts in diverge.values():
959 967 divergeset.update(dsts)
960 968 for dsts in renamedelete1.values():
961 969 renamedeleteset.update(dsts)
962 970 for dsts in renamedelete2.values():
963 971 renamedeleteset.update(dsts)
964 972
965 973 repo.ui.debug(
966 974 b" all copies found (* = to merge, ! = divergent, "
967 975 b"% = renamed and deleted):\n"
968 976 )
969 977 for side, copies in ((b"local", copies1), (b"remote", copies2)):
970 978 if not copies:
971 979 continue
972 980 repo.ui.debug(b" on %s side:\n" % side)
973 981 for f in sorted(copies):
974 982 note = b""
975 983 if f in copy1 or f in copy2:
976 984 note += b"*"
977 985 if f in divergeset:
978 986 note += b"!"
979 987 if f in renamedeleteset:
980 988 note += b"%"
981 989 repo.ui.debug(
982 990 b" src: '%s' -> dst: '%s' %s\n" % (copies[f], f, note)
983 991 )
984 992 del renamedeleteset
985 993 del divergeset
986 994
987 995 repo.ui.debug(b" checking for directory renames\n")
988 996
989 997 dirmove1, movewithdir2 = _dir_renames(repo, c1, copy1, copies1, u2fn)
990 998 dirmove2, movewithdir1 = _dir_renames(repo, c2, copy2, copies2, u1fn)
991 999
992 1000 branch_copies1 = branch_copies(copy1, renamedelete1, dirmove1, movewithdir1)
993 1001 branch_copies2 = branch_copies(copy2, renamedelete2, dirmove2, movewithdir2)
994 1002
995 1003 return branch_copies1, branch_copies2, diverge
996 1004
997 1005
998 1006 def _dir_renames(repo, ctx, copy, fullcopy, addedfilesfn):
999 1007 """Finds moved directories and files that should move with them.
1000 1008
1001 1009 ctx: the context for one of the sides
1002 1010 copy: files copied on the same side (as ctx)
1003 1011 fullcopy: files copied on the same side (as ctx), including those that
1004 1012 merge.manifestmerge() won't care about
1005 1013 addedfilesfn: function returning added files on the other side (compared to
1006 1014 ctx)
1007 1015 """
1008 1016 # generate a directory move map
1009 1017 invalid = set()
1010 1018 dirmove = {}
1011 1019
1012 1020 # examine each file copy for a potential directory move, which is
1013 1021 # when all the files in a directory are moved to a new directory
1014 1022 for dst, src in pycompat.iteritems(fullcopy):
1015 1023 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
1016 1024 if dsrc in invalid:
1017 1025 # already seen to be uninteresting
1018 1026 continue
1019 1027 elif ctx.hasdir(dsrc) and ctx.hasdir(ddst):
1020 1028 # directory wasn't entirely moved locally
1021 1029 invalid.add(dsrc)
1022 1030 elif dsrc in dirmove and dirmove[dsrc] != ddst:
1023 1031 # files from the same directory moved to two different places
1024 1032 invalid.add(dsrc)
1025 1033 else:
1026 1034 # looks good so far
1027 1035 dirmove[dsrc] = ddst
1028 1036
1029 1037 for i in invalid:
1030 1038 if i in dirmove:
1031 1039 del dirmove[i]
1032 1040 del invalid
1033 1041
1034 1042 if not dirmove:
1035 1043 return {}, {}
1036 1044
1037 1045 dirmove = {k + b"/": v + b"/" for k, v in pycompat.iteritems(dirmove)}
1038 1046
1039 1047 for d in dirmove:
1040 1048 repo.ui.debug(
1041 1049 b" discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d])
1042 1050 )
1043 1051
1044 1052 movewithdir = {}
1045 1053 # check unaccounted nonoverlapping files against directory moves
1046 1054 for f in addedfilesfn():
1047 1055 if f not in fullcopy:
1048 1056 for d in dirmove:
1049 1057 if f.startswith(d):
1050 1058 # new file added in a directory that was moved, move it
1051 1059 df = dirmove[d] + f[len(d) :]
1052 1060 if df not in copy:
1053 1061 movewithdir[f] = df
1054 1062 repo.ui.debug(
1055 1063 b" pending file src: '%s' -> dst: '%s'\n"
1056 1064 % (f, df)
1057 1065 )
1058 1066 break
1059 1067
1060 1068 return dirmove, movewithdir
1061 1069
1062 1070
1063 1071 def _heuristicscopytracing(repo, c1, c2, base):
1064 1072 """Fast copytracing using filename heuristics
1065 1073
1066 1074 Assumes that moves or renames are of following two types:
1067 1075
1068 1076 1) Inside a directory only (same directory name but different filenames)
1069 1077 2) Move from one directory to another
1070 1078 (same filenames but different directory names)
1071 1079
1072 1080 Works only when there are no merge commits in the "source branch".
1073 1081 Source branch is commits from base up to c2 not including base.
1074 1082
1075 1083 If merge is involved it fallbacks to _fullcopytracing().
1076 1084
1077 1085 Can be used by setting the following config:
1078 1086
1079 1087 [experimental]
1080 1088 copytrace = heuristics
1081 1089
1082 1090 In some cases the copy/move candidates found by heuristics can be very large
1083 1091 in number and that will make the algorithm slow. The number of possible
1084 1092 candidates to check can be limited by using the config
1085 1093 `experimental.copytrace.movecandidateslimit` which defaults to 100.
1086 1094 """
1087 1095
1088 1096 if c1.rev() is None:
1089 1097 c1 = c1.p1()
1090 1098 if c2.rev() is None:
1091 1099 c2 = c2.p1()
1092 1100
1093 1101 changedfiles = set()
1094 1102 m1 = c1.manifest()
1095 1103 if not repo.revs(b'%d::%d', base.rev(), c2.rev()):
1096 1104 # If base is not in c2 branch, we switch to fullcopytracing
1097 1105 repo.ui.debug(
1098 1106 b"switching to full copytracing as base is not "
1099 1107 b"an ancestor of c2\n"
1100 1108 )
1101 1109 return _fullcopytracing(repo, c1, c2, base)
1102 1110
1103 1111 ctx = c2
1104 1112 while ctx != base:
1105 1113 if len(ctx.parents()) == 2:
1106 1114 # To keep things simple let's not handle merges
1107 1115 repo.ui.debug(b"switching to full copytracing because of merges\n")
1108 1116 return _fullcopytracing(repo, c1, c2, base)
1109 1117 changedfiles.update(ctx.files())
1110 1118 ctx = ctx.p1()
1111 1119
1112 1120 copies2 = {}
1113 1121 cp = _forwardcopies(base, c2)
1114 1122 for dst, src in pycompat.iteritems(cp):
1115 1123 if src in m1:
1116 1124 copies2[dst] = src
1117 1125
1118 1126 # file is missing if it isn't present in the destination, but is present in
1119 1127 # the base and present in the source.
1120 1128 # Presence in the base is important to exclude added files, presence in the
1121 1129 # source is important to exclude removed files.
1122 1130 filt = lambda f: f not in m1 and f in base and f in c2
1123 1131 missingfiles = [f for f in changedfiles if filt(f)]
1124 1132
1125 1133 copies1 = {}
1126 1134 if missingfiles:
1127 1135 basenametofilename = collections.defaultdict(list)
1128 1136 dirnametofilename = collections.defaultdict(list)
1129 1137
1130 1138 for f in m1.filesnotin(base.manifest()):
1131 1139 basename = os.path.basename(f)
1132 1140 dirname = os.path.dirname(f)
1133 1141 basenametofilename[basename].append(f)
1134 1142 dirnametofilename[dirname].append(f)
1135 1143
1136 1144 for f in missingfiles:
1137 1145 basename = os.path.basename(f)
1138 1146 dirname = os.path.dirname(f)
1139 1147 samebasename = basenametofilename[basename]
1140 1148 samedirname = dirnametofilename[dirname]
1141 1149 movecandidates = samebasename + samedirname
1142 1150 # f is guaranteed to be present in c2, that's why
1143 1151 # c2.filectx(f) won't fail
1144 1152 f2 = c2.filectx(f)
1145 1153 # we can have a lot of candidates which can slow down the heuristics
1146 1154 # config value to limit the number of candidates moves to check
1147 1155 maxcandidates = repo.ui.configint(
1148 1156 b'experimental', b'copytrace.movecandidateslimit'
1149 1157 )
1150 1158
1151 1159 if len(movecandidates) > maxcandidates:
1152 1160 repo.ui.status(
1153 1161 _(
1154 1162 b"skipping copytracing for '%s', more "
1155 1163 b"candidates than the limit: %d\n"
1156 1164 )
1157 1165 % (f, len(movecandidates))
1158 1166 )
1159 1167 continue
1160 1168
1161 1169 for candidate in movecandidates:
1162 1170 f1 = c1.filectx(candidate)
1163 1171 if _related(f1, f2):
1164 1172 # if there are a few related copies then we'll merge
1165 1173 # changes into all of them. This matches the behaviour
1166 1174 # of upstream copytracing
1167 1175 copies1[candidate] = f
1168 1176
1169 1177 return branch_copies(copies1), branch_copies(copies2), {}
1170 1178
1171 1179
1172 1180 def _related(f1, f2):
1173 1181 """return True if f1 and f2 filectx have a common ancestor
1174 1182
1175 1183 Walk back to common ancestor to see if the two files originate
1176 1184 from the same file. Since workingfilectx's rev() is None it messes
1177 1185 up the integer comparison logic, hence the pre-step check for
1178 1186 None (f1 and f2 can only be workingfilectx's initially).
1179 1187 """
1180 1188
1181 1189 if f1 == f2:
1182 1190 return True # a match
1183 1191
1184 1192 g1, g2 = f1.ancestors(), f2.ancestors()
1185 1193 try:
1186 1194 f1r, f2r = f1.linkrev(), f2.linkrev()
1187 1195
1188 1196 if f1r is None:
1189 1197 f1 = next(g1)
1190 1198 if f2r is None:
1191 1199 f2 = next(g2)
1192 1200
1193 1201 while True:
1194 1202 f1r, f2r = f1.linkrev(), f2.linkrev()
1195 1203 if f1r > f2r:
1196 1204 f1 = next(g1)
1197 1205 elif f2r > f1r:
1198 1206 f2 = next(g2)
1199 1207 else: # f1 and f2 point to files in the same linkrev
1200 1208 return f1 == f2 # true if they point to the same file
1201 1209 except StopIteration:
1202 1210 return False
1203 1211
1204 1212
1205 1213 def graftcopies(wctx, ctx, base):
1206 1214 """reproduce copies between base and ctx in the wctx
1207 1215
1208 1216 Unlike mergecopies(), this function will only consider copies between base
1209 1217 and ctx; it will ignore copies between base and wctx. Also unlike
1210 1218 mergecopies(), this function will apply copies to the working copy (instead
1211 1219 of just returning information about the copies). That makes it cheaper
1212 1220 (especially in the common case of base==ctx.p1()) and useful also when
1213 1221 experimental.copytrace=off.
1214 1222
1215 1223 merge.update() will have already marked most copies, but it will only
1216 1224 mark copies if it thinks the source files are related (see
1217 1225 merge._related()). It will also not mark copies if the file wasn't modified
1218 1226 on the local side. This function adds the copies that were "missed"
1219 1227 by merge.update().
1220 1228 """
1221 1229 new_copies = pathcopies(base, ctx)
1222 1230 parent = wctx.p1()
1223 1231 _filter(parent, wctx, new_copies)
1224 1232 # extra filtering to drop copy information for files that existed before
1225 1233 # the graft (otherwise we would create merge filelog for non-merge commit
1226 1234 for dest, __ in list(new_copies.items()):
1227 1235 if dest in parent:
1228 1236 del new_copies[dest]
1229 1237 for dst, src in pycompat.iteritems(new_copies):
1230 1238 wctx[dst].markcopied(src)
@@ -1,721 +1,725 b''
1 1 #testcases filelog compatibility changeset sidedata
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [extensions]
5 5 > rebase=
6 6 > [alias]
7 7 > l = log -G -T '{rev} {desc}\n{files}\n'
8 8 > EOF
9 9
10 10 #if compatibility
11 11 $ cat >> $HGRCPATH << EOF
12 12 > [experimental]
13 13 > copies.read-from = compatibility
14 14 > EOF
15 15 #endif
16 16
17 17 #if changeset
18 18 $ cat >> $HGRCPATH << EOF
19 19 > [experimental]
20 20 > copies.read-from = changeset-only
21 21 > copies.write-to = changeset-only
22 22 > EOF
23 23 #endif
24 24
25 25 #if sidedata
26 26 $ cat >> $HGRCPATH << EOF
27 27 > [format]
28 28 > exp-use-copies-side-data-changeset = yes
29 29 > EOF
30 30 #endif
31 31
32 32 $ REPONUM=0
33 33 $ newrepo() {
34 34 > cd $TESTTMP
35 35 > REPONUM=`expr $REPONUM + 1`
36 36 > hg init repo-$REPONUM
37 37 > cd repo-$REPONUM
38 38 > }
39 39
40 40 Simple rename case
41 41 $ newrepo
42 42 $ echo x > x
43 43 $ hg ci -Aqm 'add x'
44 44 $ hg mv x y
45 45 $ hg debugp1copies
46 46 x -> y
47 47 $ hg debugp2copies
48 48 $ hg ci -m 'rename x to y'
49 49 $ hg l
50 50 @ 1 rename x to y
51 51 | x y
52 52 o 0 add x
53 53 x
54 54 $ hg debugp1copies -r 1
55 55 x -> y
56 56 $ hg debugpathcopies 0 1
57 57 x -> y
58 58 $ hg debugpathcopies 1 0
59 59 y -> x
60 60 Test filtering copies by path. We do filtering by destination.
61 61 $ hg debugpathcopies 0 1 x
62 62 $ hg debugpathcopies 1 0 x
63 63 y -> x
64 64 $ hg debugpathcopies 0 1 y
65 65 x -> y
66 66 $ hg debugpathcopies 1 0 y
67 67
68 68 Copies not including commit changes
69 69 $ newrepo
70 70 $ echo x > x
71 71 $ hg ci -Aqm 'add x'
72 72 $ hg mv x y
73 73 $ hg debugpathcopies . .
74 74 $ hg debugpathcopies . 'wdir()'
75 75 x -> y
76 76 $ hg debugpathcopies 'wdir()' .
77 77 y -> x
78 78
79 79 Copy a file onto another file
80 80 $ newrepo
81 81 $ echo x > x
82 82 $ echo y > y
83 83 $ hg ci -Aqm 'add x and y'
84 84 $ hg cp -f x y
85 85 $ hg debugp1copies
86 86 x -> y
87 87 $ hg debugp2copies
88 88 $ hg ci -m 'copy x onto y'
89 89 $ hg l
90 90 @ 1 copy x onto y
91 91 | y
92 92 o 0 add x and y
93 93 x y
94 94 $ hg debugp1copies -r 1
95 95 x -> y
96 96 $ hg debugpathcopies 0 1
97 97 x -> y (no-filelog !)
98 $ hg debugpathcopies 0 1 --config devel.copy-tracing.trace-all-files=yes
99 x -> y
98 100
99 101 Copy a file onto another file with same content. If metadata is stored in changeset, this does not
100 102 produce a new filelog entry. The changeset's "files" entry should still list the file.
101 103 $ newrepo
102 104 $ echo x > x
103 105 $ echo x > x2
104 106 $ hg ci -Aqm 'add x and x2 with same content'
105 107 $ hg cp -f x x2
106 108 $ hg ci -m 'copy x onto x2'
107 109 $ hg l
108 110 @ 1 copy x onto x2
109 111 | x2
110 112 o 0 add x and x2 with same content
111 113 x x2
112 114 $ hg debugp1copies -r 1
113 115 x -> x2
114 116 $ hg debugpathcopies 0 1
115 117 x -> x2 (no-filelog !)
118 $ hg debugpathcopies 0 1 --config devel.copy-tracing.trace-all-files=yes
119 x -> x2
116 120
117 121 Rename file in a loop: x->y->z->x
118 122 $ newrepo
119 123 $ echo x > x
120 124 $ hg ci -Aqm 'add x'
121 125 $ hg mv x y
122 126 $ hg debugp1copies
123 127 x -> y
124 128 $ hg debugp2copies
125 129 $ hg ci -m 'rename x to y'
126 130 $ hg mv y z
127 131 $ hg ci -m 'rename y to z'
128 132 $ hg mv z x
129 133 $ hg ci -m 'rename z to x'
130 134 $ hg l
131 135 @ 3 rename z to x
132 136 | x z
133 137 o 2 rename y to z
134 138 | y z
135 139 o 1 rename x to y
136 140 | x y
137 141 o 0 add x
138 142 x
139 143 $ hg debugpathcopies 0 3
140 144
141 145 Copy x to z, then remove z, then copy x2 (same content as x) to z. With copy metadata in the
142 146 changeset, the two copies here will have the same filelog entry, so ctx['z'].introrev() might point
143 147 to the first commit that added the file. We should still report the copy as being from x2.
144 148 $ newrepo
145 149 $ echo x > x
146 150 $ echo x > x2
147 151 $ hg ci -Aqm 'add x and x2 with same content'
148 152 $ hg cp x z
149 153 $ hg ci -qm 'copy x to z'
150 154 $ hg rm z
151 155 $ hg ci -m 'remove z'
152 156 $ hg cp x2 z
153 157 $ hg ci -m 'copy x2 to z'
154 158 $ hg l
155 159 @ 3 copy x2 to z
156 160 | z
157 161 o 2 remove z
158 162 | z
159 163 o 1 copy x to z
160 164 | z
161 165 o 0 add x and x2 with same content
162 166 x x2
163 167 $ hg debugp1copies -r 3
164 168 x2 -> z
165 169 $ hg debugpathcopies 0 3
166 170 x2 -> z
167 171
168 172 Create x and y, then rename them both to the same name, but on different sides of a fork
169 173 $ newrepo
170 174 $ echo x > x
171 175 $ echo y > y
172 176 $ hg ci -Aqm 'add x and y'
173 177 $ hg mv x z
174 178 $ hg ci -qm 'rename x to z'
175 179 $ hg co -q 0
176 180 $ hg mv y z
177 181 $ hg ci -qm 'rename y to z'
178 182 $ hg l
179 183 @ 2 rename y to z
180 184 | y z
181 185 | o 1 rename x to z
182 186 |/ x z
183 187 o 0 add x and y
184 188 x y
185 189 $ hg debugpathcopies 1 2
186 190 z -> x
187 191 y -> z
188 192
189 193 Fork renames x to y on one side and removes x on the other
190 194 $ newrepo
191 195 $ echo x > x
192 196 $ hg ci -Aqm 'add x'
193 197 $ hg mv x y
194 198 $ hg ci -m 'rename x to y'
195 199 $ hg co -q 0
196 200 $ hg rm x
197 201 $ hg ci -m 'remove x'
198 202 created new head
199 203 $ hg l
200 204 @ 2 remove x
201 205 | x
202 206 | o 1 rename x to y
203 207 |/ x y
204 208 o 0 add x
205 209 x
206 210 $ hg debugpathcopies 1 2
207 211
208 212 Merge rename from other branch
209 213 $ newrepo
210 214 $ echo x > x
211 215 $ hg ci -Aqm 'add x'
212 216 $ hg mv x y
213 217 $ hg ci -m 'rename x to y'
214 218 $ hg co -q 0
215 219 $ echo z > z
216 220 $ hg ci -Aqm 'add z'
217 221 $ hg merge -q 1
218 222 $ hg debugp1copies
219 223 $ hg debugp2copies
220 224 $ hg ci -m 'merge rename from p2'
221 225 $ hg l
222 226 @ 3 merge rename from p2
223 227 |\
224 228 | o 2 add z
225 229 | | z
226 230 o | 1 rename x to y
227 231 |/ x y
228 232 o 0 add x
229 233 x
230 234 Perhaps we should indicate the rename here, but `hg status` is documented to be weird during
231 235 merges, so...
232 236 $ hg debugp1copies -r 3
233 237 $ hg debugp2copies -r 3
234 238 $ hg debugpathcopies 0 3
235 239 x -> y
236 240 $ hg debugpathcopies 1 2
237 241 y -> x
238 242 $ hg debugpathcopies 1 3
239 243 $ hg debugpathcopies 2 3
240 244 x -> y
241 245
242 246 Copy file from either side in a merge
243 247 $ newrepo
244 248 $ echo x > x
245 249 $ hg ci -Aqm 'add x'
246 250 $ hg co -q null
247 251 $ echo y > y
248 252 $ hg ci -Aqm 'add y'
249 253 $ hg merge -q 0
250 254 $ hg cp y z
251 255 $ hg debugp1copies
252 256 y -> z
253 257 $ hg debugp2copies
254 258 $ hg ci -m 'copy file from p1 in merge'
255 259 $ hg co -q 1
256 260 $ hg merge -q 0
257 261 $ hg cp x z
258 262 $ hg debugp1copies
259 263 $ hg debugp2copies
260 264 x -> z
261 265 $ hg ci -qm 'copy file from p2 in merge'
262 266 $ hg l
263 267 @ 3 copy file from p2 in merge
264 268 |\ z
265 269 +---o 2 copy file from p1 in merge
266 270 | |/ z
267 271 | o 1 add y
268 272 | y
269 273 o 0 add x
270 274 x
271 275 $ hg debugp1copies -r 2
272 276 y -> z
273 277 $ hg debugp2copies -r 2
274 278 $ hg debugpathcopies 1 2
275 279 y -> z
276 280 $ hg debugpathcopies 0 2
277 281 $ hg debugp1copies -r 3
278 282 $ hg debugp2copies -r 3
279 283 x -> z
280 284 $ hg debugpathcopies 1 3
281 285 $ hg debugpathcopies 0 3
282 286 x -> z
283 287
284 288 Copy file that exists on both sides of the merge, same content on both sides
285 289 $ newrepo
286 290 $ echo x > x
287 291 $ hg ci -Aqm 'add x on branch 1'
288 292 $ hg co -q null
289 293 $ echo x > x
290 294 $ hg ci -Aqm 'add x on branch 2'
291 295 $ hg merge -q 0
292 296 $ hg cp x z
293 297 $ hg debugp1copies
294 298 x -> z
295 299 $ hg debugp2copies
296 300 $ hg ci -qm 'merge'
297 301 $ hg l
298 302 @ 2 merge
299 303 |\ z
300 304 | o 1 add x on branch 2
301 305 | x
302 306 o 0 add x on branch 1
303 307 x
304 308 $ hg debugp1copies -r 2
305 309 x -> z
306 310 $ hg debugp2copies -r 2
307 311 It's a little weird that it shows up on both sides
308 312 $ hg debugpathcopies 1 2
309 313 x -> z
310 314 $ hg debugpathcopies 0 2
311 315 x -> z (filelog !)
312 316
313 317 Copy file that exists on both sides of the merge, different content
314 318 $ newrepo
315 319 $ echo branch1 > x
316 320 $ hg ci -Aqm 'add x on branch 1'
317 321 $ hg co -q null
318 322 $ echo branch2 > x
319 323 $ hg ci -Aqm 'add x on branch 2'
320 324 $ hg merge -q 0
321 325 warning: conflicts while merging x! (edit, then use 'hg resolve --mark')
322 326 [1]
323 327 $ echo resolved > x
324 328 $ hg resolve -m x
325 329 (no more unresolved files)
326 330 $ hg cp x z
327 331 $ hg debugp1copies
328 332 x -> z
329 333 $ hg debugp2copies
330 334 $ hg ci -qm 'merge'
331 335 $ hg l
332 336 @ 2 merge
333 337 |\ x z
334 338 | o 1 add x on branch 2
335 339 | x
336 340 o 0 add x on branch 1
337 341 x
338 342 $ hg debugp1copies -r 2
339 343 x -> z (changeset !)
340 344 x -> z (sidedata !)
341 345 $ hg debugp2copies -r 2
342 346 x -> z (no-changeset no-sidedata !)
343 347 $ hg debugpathcopies 1 2
344 348 x -> z (changeset !)
345 349 x -> z (sidedata !)
346 350 $ hg debugpathcopies 0 2
347 351 x -> z (no-changeset no-sidedata !)
348 352
349 353 Copy x->y on one side of merge and copy x->z on the other side. Pathcopies from one parent
350 354 of the merge to the merge should include the copy from the other side.
351 355 $ newrepo
352 356 $ echo x > x
353 357 $ hg ci -Aqm 'add x'
354 358 $ hg cp x y
355 359 $ hg ci -qm 'copy x to y'
356 360 $ hg co -q 0
357 361 $ hg cp x z
358 362 $ hg ci -qm 'copy x to z'
359 363 $ hg merge -q 1
360 364 $ hg ci -m 'merge copy x->y and copy x->z'
361 365 $ hg l
362 366 @ 3 merge copy x->y and copy x->z
363 367 |\
364 368 | o 2 copy x to z
365 369 | | z
366 370 o | 1 copy x to y
367 371 |/ y
368 372 o 0 add x
369 373 x
370 374 $ hg debugp1copies -r 3
371 375 $ hg debugp2copies -r 3
372 376 $ hg debugpathcopies 2 3
373 377 x -> y
374 378 $ hg debugpathcopies 1 3
375 379 x -> z
376 380
377 381 Copy x to y on one side of merge, create y and rename to z on the other side.
378 382 $ newrepo
379 383 $ echo x > x
380 384 $ hg ci -Aqm 'add x'
381 385 $ hg cp x y
382 386 $ hg ci -qm 'copy x to y'
383 387 $ hg co -q 0
384 388 $ echo y > y
385 389 $ hg ci -Aqm 'add y'
386 390 $ hg mv y z
387 391 $ hg ci -m 'rename y to z'
388 392 $ hg merge -q 1
389 393 $ hg ci -m 'merge'
390 394 $ hg l
391 395 @ 4 merge
392 396 |\
393 397 | o 3 rename y to z
394 398 | | y z
395 399 | o 2 add y
396 400 | | y
397 401 o | 1 copy x to y
398 402 |/ y
399 403 o 0 add x
400 404 x
401 405 $ hg debugp1copies -r 3
402 406 y -> z
403 407 $ hg debugp2copies -r 3
404 408 $ hg debugpathcopies 2 3
405 409 y -> z
406 410 $ hg debugpathcopies 1 3
407 411 y -> z (no-filelog !)
408 412
409 413 Create x and y, then rename x to z on one side of merge, and rename y to z and
410 414 modify z on the other side. When storing copies in the changeset, we don't
411 415 filter out copies whose target was created on the other side of the merge.
412 416 $ newrepo
413 417 $ echo x > x
414 418 $ echo y > y
415 419 $ hg ci -Aqm 'add x and y'
416 420 $ hg mv x z
417 421 $ hg ci -qm 'rename x to z'
418 422 $ hg co -q 0
419 423 $ hg mv y z
420 424 $ hg ci -qm 'rename y to z'
421 425 $ echo z >> z
422 426 $ hg ci -m 'modify z'
423 427 $ hg merge -q 1
424 428 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
425 429 [1]
426 430 $ echo z > z
427 431 $ hg resolve -qm z
428 432 $ hg ci -m 'merge 1 into 3'
429 433 Try merging the other direction too
430 434 $ hg co -q 1
431 435 $ hg merge -q 3
432 436 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
433 437 [1]
434 438 $ echo z > z
435 439 $ hg resolve -qm z
436 440 $ hg ci -m 'merge 3 into 1'
437 441 created new head
438 442 $ hg l
439 443 @ 5 merge 3 into 1
440 444 |\ z
441 445 +---o 4 merge 1 into 3
442 446 | |/ z
443 447 | o 3 modify z
444 448 | | z
445 449 | o 2 rename y to z
446 450 | | y z
447 451 o | 1 rename x to z
448 452 |/ x z
449 453 o 0 add x and y
450 454 x y
451 455 $ hg debugpathcopies 1 4
452 456 y -> z (no-filelog !)
453 457 $ hg debugpathcopies 2 4
454 458 x -> z (no-filelog !)
455 459 $ hg debugpathcopies 0 4
456 460 x -> z (filelog !)
457 461 y -> z (no-filelog !)
458 462 $ hg debugpathcopies 1 5
459 463 y -> z (no-filelog !)
460 464 $ hg debugpathcopies 2 5
461 465 x -> z (no-filelog !)
462 466 $ hg debugpathcopies 0 5
463 467 x -> z
464 468
465 469 Create x and y, then remove y and rename x to y on one side of merge, and
466 470 modify x on the other side. The modification to x from the second side
467 471 should be propagated to y.
468 472 $ newrepo
469 473 $ echo original > x
470 474 $ hg add x
471 475 $ echo unrelated > y
472 476 $ hg add y
473 477 $ hg commit -m 'add x and y'
474 478 $ hg remove y
475 479 $ hg commit -m 'remove y'
476 480 $ hg rename x y
477 481 $ hg commit -m 'rename x to y'
478 482 $ hg checkout -q 0
479 483 $ echo modified > x
480 484 $ hg commit -m 'modify x'
481 485 created new head
482 486 $ hg l
483 487 @ 3 modify x
484 488 | x
485 489 | o 2 rename x to y
486 490 | | x y
487 491 | o 1 remove y
488 492 |/ y
489 493 o 0 add x and y
490 494 x y
491 495 #if filelog
492 496 $ hg merge 2
493 497 file 'x' was deleted in other [merge rev] but was modified in local [working copy].
494 498 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
495 499 What do you want to do? u
496 500 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
497 501 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
498 502 [1]
499 503 This should ideally be "modified", but we will probably not be able to fix
500 504 that in the filelog case.
501 505 $ cat y
502 506 original
503 507 #else
504 508 $ hg merge 2
505 509 merging x and y to y
506 510 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
507 511 (branch merge, don't forget to commit)
508 512 $ cat y
509 513 modified
510 514 #endif
511 515 Same as above, but in the opposite direction
512 516 #if filelog
513 517 $ hg co -qC 2
514 518 $ hg merge 3
515 519 file 'x' was deleted in local [working copy] but was modified in other [merge rev].
516 520 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
517 521 What do you want to do? u
518 522 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
519 523 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
520 524 [1]
521 525 BROKEN: should be "modified"
522 526 $ cat y
523 527 original
524 528 #else
525 529 $ hg co -qC 2
526 530 $ hg merge 3
527 531 merging y and x to y
528 532 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
529 533 (branch merge, don't forget to commit)
530 534 $ cat y
531 535 modified
532 536 #endif
533 537
534 538 Create x and y, then rename x to z on one side of merge, and rename y to z and
535 539 then delete z on the other side.
536 540 $ newrepo
537 541 $ echo x > x
538 542 $ echo y > y
539 543 $ hg ci -Aqm 'add x and y'
540 544 $ hg mv x z
541 545 $ hg ci -qm 'rename x to z'
542 546 $ hg co -q 0
543 547 $ hg mv y z
544 548 $ hg ci -qm 'rename y to z'
545 549 $ hg rm z
546 550 $ hg ci -m 'delete z'
547 551 $ hg merge -q 1
548 552 $ echo z > z
549 553 $ hg ci -m 'merge 1 into 3'
550 554 Try merging the other direction too
551 555 $ hg co -q 1
552 556 $ hg merge -q 3
553 557 $ echo z > z
554 558 $ hg ci -m 'merge 3 into 1'
555 559 created new head
556 560 $ hg l
557 561 @ 5 merge 3 into 1
558 562 |\ z
559 563 +---o 4 merge 1 into 3
560 564 | |/ z
561 565 | o 3 delete z
562 566 | | z
563 567 | o 2 rename y to z
564 568 | | y z
565 569 o | 1 rename x to z
566 570 |/ x z
567 571 o 0 add x and y
568 572 x y
569 573 $ hg debugpathcopies 1 4
570 574 $ hg debugpathcopies 2 4
571 575 x -> z (no-filelog !)
572 576 $ hg debugpathcopies 0 4
573 577 x -> z (no-changeset no-compatibility !)
574 578 $ hg debugpathcopies 1 5
575 579 $ hg debugpathcopies 2 5
576 580 x -> z (no-filelog !)
577 581 $ hg debugpathcopies 0 5
578 582 x -> z
579 583
580 584
581 585 Test for a case in fullcopytracing algorithm where neither of the merging csets
582 586 is a descendant of the merge base. This test reflects that the algorithm
583 587 correctly finds the copies:
584 588
585 589 $ cat >> $HGRCPATH << EOF
586 590 > [experimental]
587 591 > evolution.createmarkers=True
588 592 > evolution.allowunstable=True
589 593 > EOF
590 594
591 595 $ newrepo
592 596 $ echo a > a
593 597 $ hg add a
594 598 $ hg ci -m "added a"
595 599 $ echo b > b
596 600 $ hg add b
597 601 $ hg ci -m "added b"
598 602
599 603 $ hg mv b b1
600 604 $ hg ci -m "rename b to b1"
601 605
602 606 $ hg up ".^"
603 607 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
604 608 $ echo d > d
605 609 $ hg add d
606 610 $ hg ci -m "added d"
607 611 created new head
608 612
609 613 $ echo baba >> b
610 614 $ hg ci --amend -m "added d, modified b"
611 615
612 616 $ hg l --hidden
613 617 @ 4 added d, modified b
614 618 | b d
615 619 | x 3 added d
616 620 |/ d
617 621 | o 2 rename b to b1
618 622 |/ b b1
619 623 o 1 added b
620 624 | b
621 625 o 0 added a
622 626 a
623 627
624 628 Grafting revision 4 on top of revision 2, showing that it respect the rename:
625 629
626 630 $ hg up 2 -q
627 631 $ hg graft -r 4 --base 3 --hidden
628 632 grafting 4:af28412ec03c "added d, modified b" (tip) (no-changeset !)
629 633 grafting 4:6325ca0b7a1c "added d, modified b" (tip) (changeset !)
630 634 merging b1 and b to b1
631 635
632 636 $ hg l -l1 -p
633 637 @ 5 added d, modified b
634 638 | b1
635 639 ~ diff -r 5a4825cc2926 -r 94a2f1a0e8e2 b1 (no-changeset !)
636 640 ~ diff -r 0a0ed3b3251c -r d544fb655520 b1 (changeset !)
637 641 --- a/b1 Thu Jan 01 00:00:00 1970 +0000
638 642 +++ b/b1 Thu Jan 01 00:00:00 1970 +0000
639 643 @@ -1,1 +1,2 @@
640 644 b
641 645 +baba
642 646
643 647 Test to make sure that fullcopytracing algorithm doesn't fail when neither of the
644 648 merging csets is a descendant of the base.
645 649 -------------------------------------------------------------------------------------------------
646 650
647 651 $ newrepo
648 652 $ echo a > a
649 653 $ hg add a
650 654 $ hg ci -m "added a"
651 655 $ echo b > b
652 656 $ hg add b
653 657 $ hg ci -m "added b"
654 658
655 659 $ echo foobar > willconflict
656 660 $ hg add willconflict
657 661 $ hg ci -m "added willconflict"
658 662 $ echo c > c
659 663 $ hg add c
660 664 $ hg ci -m "added c"
661 665
662 666 $ hg l
663 667 @ 3 added c
664 668 | c
665 669 o 2 added willconflict
666 670 | willconflict
667 671 o 1 added b
668 672 | b
669 673 o 0 added a
670 674 a
671 675
672 676 $ hg up ".^^"
673 677 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
674 678 $ echo d > d
675 679 $ hg add d
676 680 $ hg ci -m "added d"
677 681 created new head
678 682
679 683 $ echo barfoo > willconflict
680 684 $ hg add willconflict
681 685 $ hg ci --amend -m "added willconflict and d"
682 686
683 687 $ hg l
684 688 @ 5 added willconflict and d
685 689 | d willconflict
686 690 | o 3 added c
687 691 | | c
688 692 | o 2 added willconflict
689 693 |/ willconflict
690 694 o 1 added b
691 695 | b
692 696 o 0 added a
693 697 a
694 698
695 699 $ hg rebase -r . -d 2 -t :other
696 700 rebasing 5:5018b1509e94 tip "added willconflict and d" (no-changeset !)
697 701 rebasing 5:af8d273bf580 tip "added willconflict and d" (changeset !)
698 702
699 703 $ hg up 3 -q
700 704 $ hg l --hidden
701 705 o 6 added willconflict and d
702 706 | d willconflict
703 707 | x 5 added willconflict and d
704 708 | | d willconflict
705 709 | | x 4 added d
706 710 | |/ d
707 711 +---@ 3 added c
708 712 | | c
709 713 o | 2 added willconflict
710 714 |/ willconflict
711 715 o 1 added b
712 716 | b
713 717 o 0 added a
714 718 a
715 719
716 720 Now if we trigger a merge between revision 3 and 6 using base revision 4,
717 721 neither of the merging csets will be a descendant of the base revision:
718 722
719 723 $ hg graft -r 6 --base 4 --hidden -t :other
720 724 grafting 6:99802e4f1e46 "added willconflict and d" (tip) (no-changeset !)
721 725 grafting 6:b19f0df72728 "added willconflict and d" (tip) (changeset !)
@@ -1,374 +1,385 b''
1 1 $ mkdir part1
2 2 $ cd part1
3 3
4 4 $ hg init
5 5 $ echo a > a
6 6 $ hg add a
7 7 $ hg commit -m "1"
8 8 $ hg status
9 9 $ hg copy a b
10 10 $ hg --config ui.portablefilenames=abort copy a con.xml
11 11 abort: filename contains 'con', which is reserved on Windows: con.xml
12 12 [10]
13 13 $ hg status
14 14 A b
15 15 $ hg sum
16 16 parent: 0:c19d34741b0a tip
17 17 1
18 18 branch: default
19 19 commit: 1 copied
20 20 update: (current)
21 21 phases: 1 draft
22 22 $ hg --debug commit -m "2"
23 23 committing files:
24 24 b
25 25 b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
26 26 committing manifest
27 27 committing changelog
28 28 updating the branch cache
29 29 committed changeset 1:93580a2c28a50a56f63526fb305067e6fbf739c4
30 30
31 31 we should see two history entries
32 32
33 33 $ hg history -v
34 34 changeset: 1:93580a2c28a5
35 35 tag: tip
36 36 user: test
37 37 date: Thu Jan 01 00:00:00 1970 +0000
38 38 files: b
39 39 description:
40 40 2
41 41
42 42
43 43 changeset: 0:c19d34741b0a
44 44 user: test
45 45 date: Thu Jan 01 00:00:00 1970 +0000
46 46 files: a
47 47 description:
48 48 1
49 49
50 50
51 51
52 52 we should see one log entry for a
53 53
54 54 $ hg log a
55 55 changeset: 0:c19d34741b0a
56 56 user: test
57 57 date: Thu Jan 01 00:00:00 1970 +0000
58 58 summary: 1
59 59
60 60
61 61 this should show a revision linked to changeset 0
62 62
63 63 $ hg debugindex a
64 64 rev linkrev nodeid p1 p2
65 65 0 0 b789fdd96dc2 000000000000 000000000000
66 66
67 67 we should see one log entry for b
68 68
69 69 $ hg log b
70 70 changeset: 1:93580a2c28a5
71 71 tag: tip
72 72 user: test
73 73 date: Thu Jan 01 00:00:00 1970 +0000
74 74 summary: 2
75 75
76 76
77 77 this should show a revision linked to changeset 1
78 78
79 79 $ hg debugindex b
80 80 rev linkrev nodeid p1 p2
81 81 0 1 37d9b5d994ea 000000000000 000000000000
82 82
83 83 this should show the rename information in the metadata
84 84
85 85 $ hg debugdata b 0 | head -3 | tail -2
86 86 copy: a
87 87 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
88 88
89 89 #if reporevlogstore
90 90 $ md5sum.py .hg/store/data/b.i
91 91 44913824c8f5890ae218f9829535922e .hg/store/data/b.i
92 92 #endif
93 93 $ hg cat b > bsum
94 94 $ md5sum.py bsum
95 95 60b725f10c9c85c70d97880dfe8191b3 bsum
96 96 $ hg cat a > asum
97 97 $ md5sum.py asum
98 98 60b725f10c9c85c70d97880dfe8191b3 asum
99 99 $ hg verify
100 100 checking changesets
101 101 checking manifests
102 102 crosschecking files in changesets and manifests
103 103 checking files
104 104 checked 2 changesets with 2 changes to 2 files
105 105
106 106 $ cd ..
107 107
108 108
109 109 $ mkdir part2
110 110 $ cd part2
111 111
112 112 $ hg init
113 113 $ echo foo > foo
114 114 should fail - foo is not managed
115 115 $ hg mv foo bar
116 116 foo: not copying - file is not managed
117 117 abort: no files to copy
118 118 [10]
119 119 $ hg st -A
120 120 ? foo
121 121 respects ui.relative-paths
122 122 $ mkdir dir
123 123 $ cd dir
124 124 $ hg mv ../foo ../bar
125 125 ../foo: not copying - file is not managed
126 126 abort: no files to copy
127 127 [10]
128 128 $ hg mv ../foo ../bar --config ui.relative-paths=yes
129 129 ../foo: not copying - file is not managed
130 130 abort: no files to copy
131 131 [10]
132 132 $ hg mv ../foo ../bar --config ui.relative-paths=no
133 133 foo: not copying - file is not managed
134 134 abort: no files to copy
135 135 [10]
136 136 $ cd ..
137 137 $ rmdir dir
138 138 $ hg add foo
139 139 dry-run; print a warning that this is not a real copy; foo is added
140 140 $ hg mv --dry-run foo bar
141 141 foo has not been committed yet, so no copy data will be stored for bar.
142 142 $ hg st -A
143 143 A foo
144 144 should print a warning that this is not a real copy; bar is added
145 145 $ hg mv foo bar
146 146 foo has not been committed yet, so no copy data will be stored for bar.
147 147 $ hg st -A
148 148 A bar
149 149 should print a warning that this is not a real copy; foo is added
150 150 $ hg cp bar foo
151 151 bar has not been committed yet, so no copy data will be stored for foo.
152 152 $ hg rm -f bar
153 153 $ rm bar
154 154 $ hg st -A
155 155 A foo
156 156 $ hg commit -m1
157 157
158 158 moving a missing file
159 159 $ rm foo
160 160 $ hg mv foo foo3
161 161 foo: deleted in working directory
162 162 foo3 does not exist!
163 163 $ hg up -qC .
164 164
165 165 copy --after to a nonexistent target filename
166 166 $ hg cp -A foo dummy
167 167 foo: not recording copy - dummy does not exist
168 168 [1]
169 169
170 170 dry-run; should show that foo is clean
171 171 $ hg copy --dry-run foo bar
172 172 $ hg st -A
173 173 C foo
174 174 should show copy
175 175 $ hg copy foo bar
176 176 $ hg st -C
177 177 A bar
178 178 foo
179 179
180 180 shouldn't show copy
181 181 $ hg commit -m2
182 182 $ hg st -C
183 183
184 184 should match
185 185 $ hg debugindex foo
186 186 rev linkrev nodeid p1 p2
187 187 0 0 2ed2a3912a0b 000000000000 000000000000
188 188 $ hg debugrename bar
189 189 bar renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
190 190
191 191 $ echo bleah > foo
192 192 $ echo quux > bar
193 193 $ hg commit -m3
194 194
195 195 should not be renamed
196 196 $ hg debugrename bar
197 197 bar not renamed
198 198
199 199 $ hg copy -f foo bar
200 200 should show copy
201 201 $ hg st -C
202 202 M bar
203 203 foo
204 204
205 205 XXX: filtering lfilesrepo.status() in 3.3-rc causes the copy source to not be
206 206 displayed.
207 207 $ hg st -C --config extensions.largefiles=
208 208 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
209 209 M bar
210 210 foo
211 211
212 212 $ hg commit -m3
213 213
214 214 should show no parents for tip
215 215 $ hg debugindex bar
216 216 rev linkrev nodeid p1 p2
217 217 0 1 7711d36246cc 000000000000 000000000000
218 218 1 2 bdf70a2b8d03 7711d36246cc 000000000000
219 219 2 3 b2558327ea8d 000000000000 000000000000
220 220 should match
221 221 $ hg debugindex foo
222 222 rev linkrev nodeid p1 p2
223 223 0 0 2ed2a3912a0b 000000000000 000000000000
224 224 1 2 dd12c926cf16 2ed2a3912a0b 000000000000
225 225 $ hg debugrename bar
226 226 bar renamed from foo:dd12c926cf165e3eb4cf87b084955cb617221c17
227 227
228 228 should show no copies
229 229 $ hg st -C
230 230
231 note: since filelog based copy tracing only trace copy for new file, the copy information here is not displayed.
232
233 $ hg status --copies --change .
234 M bar
235
236 They are a devel option to walk all file and fine this information anyway.
237
238 $ hg status --copies --change . --config devel.copy-tracing.trace-all-files=yes
239 M bar
240 foo
241
231 242 copy --after on an added file
232 243 $ cp bar baz
233 244 $ hg add baz
234 245 $ hg cp -A bar baz
235 246 $ hg st -C
236 247 A baz
237 248 bar
238 249
239 250 foo was clean:
240 251 $ hg st -AC foo
241 252 C foo
242 253 Trying to copy on top of an existing file fails,
243 254 $ hg copy -A bar foo
244 255 foo: not overwriting - file already committed
245 256 ('hg copy --after --force' to replace the file by recording a copy)
246 257 [1]
247 258 same error without the --after, so the user doesn't have to go through
248 259 two hints:
249 260 $ hg copy bar foo
250 261 foo: not overwriting - file already committed
251 262 ('hg copy --force' to replace the file by recording a copy)
252 263 [1]
253 264 but it's considered modified after a copy --after --force
254 265 $ hg copy -Af bar foo
255 266 $ hg st -AC foo
256 267 M foo
257 268 bar
258 269 The hint for a file that exists but is not in file history doesn't
259 270 mention --force:
260 271 $ touch xyzzy
261 272 $ hg cp bar xyzzy
262 273 xyzzy: not overwriting - file exists
263 274 ('hg copy --after' to record the copy)
264 275 [1]
265 276 $ hg co -qC .
266 277 $ rm baz xyzzy
267 278
268 279
269 280 Test unmarking copy of a single file
270 281
271 282 # Set up by creating a copy
272 283 $ hg cp bar baz
273 284 # Test uncopying a non-existent file
274 285 $ hg copy --forget non-existent
275 286 non-existent: $ENOENT$
276 287 # Test uncopying an tracked but unrelated file
277 288 $ hg copy --forget foo
278 289 foo: not unmarking as copy - file is not marked as copied
279 290 # Test uncopying a copy source
280 291 $ hg copy --forget bar
281 292 bar: not unmarking as copy - file is not marked as copied
282 293 # baz should still be marked as a copy
283 294 $ hg st -C
284 295 A baz
285 296 bar
286 297 # Test the normal case
287 298 $ hg copy --forget baz
288 299 $ hg st -C
289 300 A baz
290 301 # Test uncopy with matching an non-matching patterns
291 302 $ hg cp bar baz --after
292 303 $ hg copy --forget bar baz
293 304 bar: not unmarking as copy - file is not marked as copied
294 305 $ hg st -C
295 306 A baz
296 307 # Test uncopy with no exact matches
297 308 $ hg cp bar baz --after
298 309 $ hg copy --forget .
299 310 $ hg st -C
300 311 A baz
301 312 $ hg forget baz
302 313 $ rm baz
303 314
304 315 Test unmarking copy of a directory
305 316
306 317 $ mkdir dir
307 318 $ echo foo > dir/foo
308 319 $ echo bar > dir/bar
309 320 $ hg add dir
310 321 adding dir/bar
311 322 adding dir/foo
312 323 $ hg ci -m 'add dir/'
313 324 $ hg cp dir dir2
314 325 copying dir/bar to dir2/bar
315 326 copying dir/foo to dir2/foo
316 327 $ touch dir2/untracked
317 328 $ hg copy --forget dir2
318 329 $ hg st -C
319 330 A dir2/bar
320 331 A dir2/foo
321 332 ? dir2/untracked
322 333 # Clean up for next test
323 334 $ hg forget dir2
324 335 removing dir2/bar
325 336 removing dir2/foo
326 337 $ rm -r dir2
327 338
328 339 Test uncopy on committed copies
329 340
330 341 # Commit some copies
331 342 $ hg cp bar baz
332 343 $ hg cp bar qux
333 344 $ hg ci -m copies
334 345 $ hg st -C --change .
335 346 A baz
336 347 bar
337 348 A qux
338 349 bar
339 350 $ base=$(hg log -r '.^' -T '{rev}')
340 351 $ hg log -G -T '{rev}:{node|short} {desc}\n' -r $base:
341 352 @ 5:a612dc2edfda copies
342 353 |
343 354 o 4:4800b1f1f38e add dir/
344 355 |
345 356 ~
346 357 # Add a dirty change on top to show that it's unaffected
347 358 $ echo dirty >> baz
348 359 $ hg st
349 360 M baz
350 361 $ cat baz
351 362 bleah
352 363 dirty
353 364 $ hg copy --forget --at-rev . baz
354 365 saved backup bundle to $TESTTMP/part2/.hg/strip-backup/a612dc2edfda-e36b4448-uncopy.hg
355 366 # The unwanted copy is no longer recorded, but the unrelated one is
356 367 $ hg st -C --change .
357 368 A baz
358 369 A qux
359 370 bar
360 371 # The old commit is gone and we have updated to the new commit
361 372 $ hg log -G -T '{rev}:{node|short} {desc}\n' -r $base:
362 373 @ 5:c45090e5effe copies
363 374 |
364 375 o 4:4800b1f1f38e add dir/
365 376 |
366 377 ~
367 378 # Working copy still has the uncommitted change
368 379 $ hg st
369 380 M baz
370 381 $ cat baz
371 382 bleah
372 383 dirty
373 384
374 385 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now