##// END OF EJS Templates
hgweb: add support to explicitly access hidden changesets...
marmoute -
r51308:4077d622 default
parent child Browse files
Show More
@@ -1,2970 +1,2975 b''
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8
9 9 import functools
10 10 import re
11 11
12 12 from . import (
13 13 encoding,
14 14 error,
15 15 )
16 16
17 17
18 18 def loadconfigtable(ui, extname, configtable):
19 19 """update config item known to the ui with the extension ones"""
20 20 for section, items in sorted(configtable.items()):
21 21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 22 knownkeys = set(knownitems)
23 23 newkeys = set(items)
24 24 for key in sorted(knownkeys & newkeys):
25 25 msg = b"extension '%s' overwrite config item '%s.%s'"
26 26 msg %= (extname, section, key)
27 27 ui.develwarn(msg, config=b'warn-config')
28 28
29 29 knownitems.update(items)
30 30
31 31
32 32 class configitem:
33 33 """represent a known config item
34 34
35 35 :section: the official config section where to find this item,
36 36 :name: the official name within the section,
37 37 :default: default value for this item,
38 38 :alias: optional list of tuples as alternatives,
39 39 :generic: this is a generic definition, match name using regular expression.
40 40 """
41 41
42 42 def __init__(
43 43 self,
44 44 section,
45 45 name,
46 46 default=None,
47 47 alias=(),
48 48 generic=False,
49 49 priority=0,
50 50 experimental=False,
51 51 ):
52 52 self.section = section
53 53 self.name = name
54 54 self.default = default
55 55 self.alias = list(alias)
56 56 self.generic = generic
57 57 self.priority = priority
58 58 self.experimental = experimental
59 59 self._re = None
60 60 if generic:
61 61 self._re = re.compile(self.name)
62 62
63 63
64 64 class itemregister(dict):
65 65 """A specialized dictionary that can handle wild-card selection"""
66 66
67 67 def __init__(self):
68 68 super(itemregister, self).__init__()
69 69 self._generics = set()
70 70
71 71 def update(self, other):
72 72 super(itemregister, self).update(other)
73 73 self._generics.update(other._generics)
74 74
75 75 def __setitem__(self, key, item):
76 76 super(itemregister, self).__setitem__(key, item)
77 77 if item.generic:
78 78 self._generics.add(item)
79 79
80 80 def get(self, key):
81 81 baseitem = super(itemregister, self).get(key)
82 82 if baseitem is not None and not baseitem.generic:
83 83 return baseitem
84 84
85 85 # search for a matching generic item
86 86 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
87 87 for item in generics:
88 88 # we use 'match' instead of 'search' to make the matching simpler
89 89 # for people unfamiliar with regular expression. Having the match
90 90 # rooted to the start of the string will produce less surprising
91 91 # result for user writing simple regex for sub-attribute.
92 92 #
93 93 # For example using "color\..*" match produces an unsurprising
94 94 # result, while using search could suddenly match apparently
95 95 # unrelated configuration that happens to contains "color."
96 96 # anywhere. This is a tradeoff where we favor requiring ".*" on
97 97 # some match to avoid the need to prefix most pattern with "^".
98 98 # The "^" seems more error prone.
99 99 if item._re.match(key):
100 100 return item
101 101
102 102 return None
103 103
104 104
105 105 coreitems = {}
106 106
107 107
108 108 def _register(configtable, *args, **kwargs):
109 109 item = configitem(*args, **kwargs)
110 110 section = configtable.setdefault(item.section, itemregister())
111 111 if item.name in section:
112 112 msg = b"duplicated config item registration for '%s.%s'"
113 113 raise error.ProgrammingError(msg % (item.section, item.name))
114 114 section[item.name] = item
115 115
116 116
117 117 # special value for case where the default is derived from other values
118 118 dynamicdefault = object()
119 119
120 120 # Registering actual config items
121 121
122 122
123 123 def getitemregister(configtable):
124 124 f = functools.partial(_register, configtable)
125 125 # export pseudo enum as configitem.*
126 126 f.dynamicdefault = dynamicdefault
127 127 return f
128 128
129 129
130 130 coreconfigitem = getitemregister(coreitems)
131 131
132 132
133 133 def _registerdiffopts(section, configprefix=b''):
134 134 coreconfigitem(
135 135 section,
136 136 configprefix + b'nodates',
137 137 default=False,
138 138 )
139 139 coreconfigitem(
140 140 section,
141 141 configprefix + b'showfunc',
142 142 default=False,
143 143 )
144 144 coreconfigitem(
145 145 section,
146 146 configprefix + b'unified',
147 147 default=None,
148 148 )
149 149 coreconfigitem(
150 150 section,
151 151 configprefix + b'git',
152 152 default=False,
153 153 )
154 154 coreconfigitem(
155 155 section,
156 156 configprefix + b'ignorews',
157 157 default=False,
158 158 )
159 159 coreconfigitem(
160 160 section,
161 161 configprefix + b'ignorewsamount',
162 162 default=False,
163 163 )
164 164 coreconfigitem(
165 165 section,
166 166 configprefix + b'ignoreblanklines',
167 167 default=False,
168 168 )
169 169 coreconfigitem(
170 170 section,
171 171 configprefix + b'ignorewseol',
172 172 default=False,
173 173 )
174 174 coreconfigitem(
175 175 section,
176 176 configprefix + b'nobinary',
177 177 default=False,
178 178 )
179 179 coreconfigitem(
180 180 section,
181 181 configprefix + b'noprefix',
182 182 default=False,
183 183 )
184 184 coreconfigitem(
185 185 section,
186 186 configprefix + b'word-diff',
187 187 default=False,
188 188 )
189 189
190 190
191 191 coreconfigitem(
192 192 b'alias',
193 193 b'.*',
194 194 default=dynamicdefault,
195 195 generic=True,
196 196 )
197 197 coreconfigitem(
198 198 b'auth',
199 199 b'cookiefile',
200 200 default=None,
201 201 )
202 202 _registerdiffopts(section=b'annotate')
203 203 # bookmarks.pushing: internal hack for discovery
204 204 coreconfigitem(
205 205 b'bookmarks',
206 206 b'pushing',
207 207 default=list,
208 208 )
209 209 # bundle.mainreporoot: internal hack for bundlerepo
210 210 coreconfigitem(
211 211 b'bundle',
212 212 b'mainreporoot',
213 213 default=b'',
214 214 )
215 215 coreconfigitem(
216 216 b'censor',
217 217 b'policy',
218 218 default=b'abort',
219 219 experimental=True,
220 220 )
221 221 coreconfigitem(
222 222 b'chgserver',
223 223 b'idletimeout',
224 224 default=3600,
225 225 )
226 226 coreconfigitem(
227 227 b'chgserver',
228 228 b'skiphash',
229 229 default=False,
230 230 )
231 231 coreconfigitem(
232 232 b'cmdserver',
233 233 b'log',
234 234 default=None,
235 235 )
236 236 coreconfigitem(
237 237 b'cmdserver',
238 238 b'max-log-files',
239 239 default=7,
240 240 )
241 241 coreconfigitem(
242 242 b'cmdserver',
243 243 b'max-log-size',
244 244 default=b'1 MB',
245 245 )
246 246 coreconfigitem(
247 247 b'cmdserver',
248 248 b'max-repo-cache',
249 249 default=0,
250 250 experimental=True,
251 251 )
252 252 coreconfigitem(
253 253 b'cmdserver',
254 254 b'message-encodings',
255 255 default=list,
256 256 )
257 257 coreconfigitem(
258 258 b'cmdserver',
259 259 b'track-log',
260 260 default=lambda: [b'chgserver', b'cmdserver', b'repocache'],
261 261 )
262 262 coreconfigitem(
263 263 b'cmdserver',
264 264 b'shutdown-on-interrupt',
265 265 default=True,
266 266 )
267 267 coreconfigitem(
268 268 b'color',
269 269 b'.*',
270 270 default=None,
271 271 generic=True,
272 272 )
273 273 coreconfigitem(
274 274 b'color',
275 275 b'mode',
276 276 default=b'auto',
277 277 )
278 278 coreconfigitem(
279 279 b'color',
280 280 b'pagermode',
281 281 default=dynamicdefault,
282 282 )
283 283 coreconfigitem(
284 284 b'command-templates',
285 285 b'graphnode',
286 286 default=None,
287 287 alias=[(b'ui', b'graphnodetemplate')],
288 288 )
289 289 coreconfigitem(
290 290 b'command-templates',
291 291 b'log',
292 292 default=None,
293 293 alias=[(b'ui', b'logtemplate')],
294 294 )
295 295 coreconfigitem(
296 296 b'command-templates',
297 297 b'mergemarker',
298 298 default=(
299 299 b'{node|short} '
300 300 b'{ifeq(tags, "tip", "", '
301 301 b'ifeq(tags, "", "", "{tags} "))}'
302 302 b'{if(bookmarks, "{bookmarks} ")}'
303 303 b'{ifeq(branch, "default", "", "{branch} ")}'
304 304 b'- {author|user}: {desc|firstline}'
305 305 ),
306 306 alias=[(b'ui', b'mergemarkertemplate')],
307 307 )
308 308 coreconfigitem(
309 309 b'command-templates',
310 310 b'pre-merge-tool-output',
311 311 default=None,
312 312 alias=[(b'ui', b'pre-merge-tool-output-template')],
313 313 )
314 314 coreconfigitem(
315 315 b'command-templates',
316 316 b'oneline-summary',
317 317 default=None,
318 318 )
319 319 coreconfigitem(
320 320 b'command-templates',
321 321 b'oneline-summary.*',
322 322 default=dynamicdefault,
323 323 generic=True,
324 324 )
325 325 _registerdiffopts(section=b'commands', configprefix=b'commit.interactive.')
326 326 coreconfigitem(
327 327 b'commands',
328 328 b'commit.post-status',
329 329 default=False,
330 330 )
331 331 coreconfigitem(
332 332 b'commands',
333 333 b'grep.all-files',
334 334 default=False,
335 335 experimental=True,
336 336 )
337 337 coreconfigitem(
338 338 b'commands',
339 339 b'merge.require-rev',
340 340 default=False,
341 341 )
342 342 coreconfigitem(
343 343 b'commands',
344 344 b'push.require-revs',
345 345 default=False,
346 346 )
347 347 coreconfigitem(
348 348 b'commands',
349 349 b'resolve.confirm',
350 350 default=False,
351 351 )
352 352 coreconfigitem(
353 353 b'commands',
354 354 b'resolve.explicit-re-merge',
355 355 default=False,
356 356 )
357 357 coreconfigitem(
358 358 b'commands',
359 359 b'resolve.mark-check',
360 360 default=b'none',
361 361 )
362 362 _registerdiffopts(section=b'commands', configprefix=b'revert.interactive.')
363 363 coreconfigitem(
364 364 b'commands',
365 365 b'show.aliasprefix',
366 366 default=list,
367 367 )
368 368 coreconfigitem(
369 369 b'commands',
370 370 b'status.relative',
371 371 default=False,
372 372 )
373 373 coreconfigitem(
374 374 b'commands',
375 375 b'status.skipstates',
376 376 default=[],
377 377 experimental=True,
378 378 )
379 379 coreconfigitem(
380 380 b'commands',
381 381 b'status.terse',
382 382 default=b'',
383 383 )
384 384 coreconfigitem(
385 385 b'commands',
386 386 b'status.verbose',
387 387 default=False,
388 388 )
389 389 coreconfigitem(
390 390 b'commands',
391 391 b'update.check',
392 392 default=None,
393 393 )
394 394 coreconfigitem(
395 395 b'commands',
396 396 b'update.requiredest',
397 397 default=False,
398 398 )
399 399 coreconfigitem(
400 400 b'committemplate',
401 401 b'.*',
402 402 default=None,
403 403 generic=True,
404 404 )
405 405 coreconfigitem(
406 406 b'convert',
407 407 b'bzr.saverev',
408 408 default=True,
409 409 )
410 410 coreconfigitem(
411 411 b'convert',
412 412 b'cvsps.cache',
413 413 default=True,
414 414 )
415 415 coreconfigitem(
416 416 b'convert',
417 417 b'cvsps.fuzz',
418 418 default=60,
419 419 )
420 420 coreconfigitem(
421 421 b'convert',
422 422 b'cvsps.logencoding',
423 423 default=None,
424 424 )
425 425 coreconfigitem(
426 426 b'convert',
427 427 b'cvsps.mergefrom',
428 428 default=None,
429 429 )
430 430 coreconfigitem(
431 431 b'convert',
432 432 b'cvsps.mergeto',
433 433 default=None,
434 434 )
435 435 coreconfigitem(
436 436 b'convert',
437 437 b'git.committeractions',
438 438 default=lambda: [b'messagedifferent'],
439 439 )
440 440 coreconfigitem(
441 441 b'convert',
442 442 b'git.extrakeys',
443 443 default=list,
444 444 )
445 445 coreconfigitem(
446 446 b'convert',
447 447 b'git.findcopiesharder',
448 448 default=False,
449 449 )
450 450 coreconfigitem(
451 451 b'convert',
452 452 b'git.remoteprefix',
453 453 default=b'remote',
454 454 )
455 455 coreconfigitem(
456 456 b'convert',
457 457 b'git.renamelimit',
458 458 default=400,
459 459 )
460 460 coreconfigitem(
461 461 b'convert',
462 462 b'git.saverev',
463 463 default=True,
464 464 )
465 465 coreconfigitem(
466 466 b'convert',
467 467 b'git.similarity',
468 468 default=50,
469 469 )
470 470 coreconfigitem(
471 471 b'convert',
472 472 b'git.skipsubmodules',
473 473 default=False,
474 474 )
475 475 coreconfigitem(
476 476 b'convert',
477 477 b'hg.clonebranches',
478 478 default=False,
479 479 )
480 480 coreconfigitem(
481 481 b'convert',
482 482 b'hg.ignoreerrors',
483 483 default=False,
484 484 )
485 485 coreconfigitem(
486 486 b'convert',
487 487 b'hg.preserve-hash',
488 488 default=False,
489 489 )
490 490 coreconfigitem(
491 491 b'convert',
492 492 b'hg.revs',
493 493 default=None,
494 494 )
495 495 coreconfigitem(
496 496 b'convert',
497 497 b'hg.saverev',
498 498 default=False,
499 499 )
500 500 coreconfigitem(
501 501 b'convert',
502 502 b'hg.sourcename',
503 503 default=None,
504 504 )
505 505 coreconfigitem(
506 506 b'convert',
507 507 b'hg.startrev',
508 508 default=None,
509 509 )
510 510 coreconfigitem(
511 511 b'convert',
512 512 b'hg.tagsbranch',
513 513 default=b'default',
514 514 )
515 515 coreconfigitem(
516 516 b'convert',
517 517 b'hg.usebranchnames',
518 518 default=True,
519 519 )
520 520 coreconfigitem(
521 521 b'convert',
522 522 b'ignoreancestorcheck',
523 523 default=False,
524 524 experimental=True,
525 525 )
526 526 coreconfigitem(
527 527 b'convert',
528 528 b'localtimezone',
529 529 default=False,
530 530 )
531 531 coreconfigitem(
532 532 b'convert',
533 533 b'p4.encoding',
534 534 default=dynamicdefault,
535 535 )
536 536 coreconfigitem(
537 537 b'convert',
538 538 b'p4.startrev',
539 539 default=0,
540 540 )
541 541 coreconfigitem(
542 542 b'convert',
543 543 b'skiptags',
544 544 default=False,
545 545 )
546 546 coreconfigitem(
547 547 b'convert',
548 548 b'svn.debugsvnlog',
549 549 default=True,
550 550 )
551 551 coreconfigitem(
552 552 b'convert',
553 553 b'svn.trunk',
554 554 default=None,
555 555 )
556 556 coreconfigitem(
557 557 b'convert',
558 558 b'svn.tags',
559 559 default=None,
560 560 )
561 561 coreconfigitem(
562 562 b'convert',
563 563 b'svn.branches',
564 564 default=None,
565 565 )
566 566 coreconfigitem(
567 567 b'convert',
568 568 b'svn.startrev',
569 569 default=0,
570 570 )
571 571 coreconfigitem(
572 572 b'convert',
573 573 b'svn.dangerous-set-commit-dates',
574 574 default=False,
575 575 )
576 576 coreconfigitem(
577 577 b'debug',
578 578 b'dirstate.delaywrite',
579 579 default=0,
580 580 )
581 581 coreconfigitem(
582 582 b'debug',
583 583 b'revlog.verifyposition.changelog',
584 584 default=b'',
585 585 )
586 586 coreconfigitem(
587 587 b'debug',
588 588 b'revlog.debug-delta',
589 589 default=False,
590 590 )
591 591 # display extra information about the bundling process
592 592 coreconfigitem(
593 593 b'debug',
594 594 b'bundling-stats',
595 595 default=False,
596 596 )
597 597 # display extra information about the unbundling process
598 598 coreconfigitem(
599 599 b'debug',
600 600 b'unbundling-stats',
601 601 default=False,
602 602 )
603 603 coreconfigitem(
604 604 b'defaults',
605 605 b'.*',
606 606 default=None,
607 607 generic=True,
608 608 )
609 609 coreconfigitem(
610 610 b'devel',
611 611 b'all-warnings',
612 612 default=False,
613 613 )
614 614 coreconfigitem(
615 615 b'devel',
616 616 b'bundle2.debug',
617 617 default=False,
618 618 )
619 619 coreconfigitem(
620 620 b'devel',
621 621 b'bundle.delta',
622 622 default=b'',
623 623 )
624 624 coreconfigitem(
625 625 b'devel',
626 626 b'cache-vfs',
627 627 default=None,
628 628 )
629 629 coreconfigitem(
630 630 b'devel',
631 631 b'check-locks',
632 632 default=False,
633 633 )
634 634 coreconfigitem(
635 635 b'devel',
636 636 b'check-relroot',
637 637 default=False,
638 638 )
639 639 # Track copy information for all file, not just "added" one (very slow)
640 640 coreconfigitem(
641 641 b'devel',
642 642 b'copy-tracing.trace-all-files',
643 643 default=False,
644 644 )
645 645 coreconfigitem(
646 646 b'devel',
647 647 b'default-date',
648 648 default=None,
649 649 )
650 650 coreconfigitem(
651 651 b'devel',
652 652 b'deprec-warn',
653 653 default=False,
654 654 )
655 655 # possible values:
656 656 # - auto (the default)
657 657 # - force-append
658 658 # - force-new
659 659 coreconfigitem(
660 660 b'devel',
661 661 b'dirstate.v2.data_update_mode',
662 662 default="auto",
663 663 )
664 664 coreconfigitem(
665 665 b'devel',
666 666 b'disableloaddefaultcerts',
667 667 default=False,
668 668 )
669 669 coreconfigitem(
670 670 b'devel',
671 671 b'warn-empty-changegroup',
672 672 default=False,
673 673 )
674 674 coreconfigitem(
675 675 b'devel',
676 676 b'legacy.exchange',
677 677 default=list,
678 678 )
679 679 # When True, revlogs use a special reference version of the nodemap, that is not
680 680 # performant but is "known" to behave properly.
681 681 coreconfigitem(
682 682 b'devel',
683 683 b'persistent-nodemap',
684 684 default=False,
685 685 )
686 686 coreconfigitem(
687 687 b'devel',
688 688 b'servercafile',
689 689 default=b'',
690 690 )
691 691 # This config option is intended for use in tests only. It is a giant
692 692 # footgun to kill security. Don't define it.
693 693 coreconfigitem(
694 694 b'devel',
695 695 b'server-insecure-exact-protocol',
696 696 default=b'',
697 697 )
698 698 coreconfigitem(
699 699 b'devel',
700 700 b'serverrequirecert',
701 701 default=False,
702 702 )
703 703 # Makes the status algorithm wait for the existence of this file
704 704 # (or until a timeout of `devel.sync.status.pre-dirstate-write-file-timeout`
705 705 # seconds) before taking the lock and writing the dirstate.
706 706 # Status signals that it's ready to wait by creating a file
707 707 # with the same name + `.waiting`.
708 708 # Useful when testing race conditions.
709 709 coreconfigitem(
710 710 b'devel',
711 711 b'sync.status.pre-dirstate-write-file',
712 712 default=None,
713 713 )
714 714 coreconfigitem(
715 715 b'devel',
716 716 b'sync.status.pre-dirstate-write-file-timeout',
717 717 default=2,
718 718 )
719 719 coreconfigitem(
720 720 b'devel',
721 721 b'sync.dirstate.post-docket-read-file',
722 722 default=None,
723 723 )
724 724 coreconfigitem(
725 725 b'devel',
726 726 b'sync.dirstate.post-docket-read-file-timeout',
727 727 default=2,
728 728 )
729 729 coreconfigitem(
730 730 b'devel',
731 731 b'sync.dirstate.pre-read-file',
732 732 default=None,
733 733 )
734 734 coreconfigitem(
735 735 b'devel',
736 736 b'sync.dirstate.pre-read-file-timeout',
737 737 default=2,
738 738 )
739 739 coreconfigitem(
740 740 b'devel',
741 741 b'strip-obsmarkers',
742 742 default=True,
743 743 )
744 744 coreconfigitem(
745 745 b'devel',
746 746 b'warn-config',
747 747 default=None,
748 748 )
749 749 coreconfigitem(
750 750 b'devel',
751 751 b'warn-config-default',
752 752 default=None,
753 753 )
754 754 coreconfigitem(
755 755 b'devel',
756 756 b'user.obsmarker',
757 757 default=None,
758 758 )
759 759 coreconfigitem(
760 760 b'devel',
761 761 b'warn-config-unknown',
762 762 default=None,
763 763 )
764 764 coreconfigitem(
765 765 b'devel',
766 766 b'debug.copies',
767 767 default=False,
768 768 )
769 769 coreconfigitem(
770 770 b'devel',
771 771 b'copy-tracing.multi-thread',
772 772 default=True,
773 773 )
774 774 coreconfigitem(
775 775 b'devel',
776 776 b'debug.extensions',
777 777 default=False,
778 778 )
779 779 coreconfigitem(
780 780 b'devel',
781 781 b'debug.repo-filters',
782 782 default=False,
783 783 )
784 784 coreconfigitem(
785 785 b'devel',
786 786 b'debug.peer-request',
787 787 default=False,
788 788 )
789 789 # If discovery.exchange-heads is False, the discovery will not start with
790 790 # remote head fetching and local head querying.
791 791 coreconfigitem(
792 792 b'devel',
793 793 b'discovery.exchange-heads',
794 794 default=True,
795 795 )
796 796 # If devel.debug.abort-update is True, then any merge with the working copy,
797 797 # e.g. [hg update], will be aborted after figuring out what needs to be done,
798 798 # but before spawning the parallel worker
799 799 coreconfigitem(
800 800 b'devel',
801 801 b'debug.abort-update',
802 802 default=False,
803 803 )
804 804 # If discovery.grow-sample is False, the sample size used in set discovery will
805 805 # not be increased through the process
806 806 coreconfigitem(
807 807 b'devel',
808 808 b'discovery.grow-sample',
809 809 default=True,
810 810 )
811 811 # When discovery.grow-sample.dynamic is True, the default, the sample size is
812 812 # adapted to the shape of the undecided set (it is set to the max of:
813 813 # <target-size>, len(roots(undecided)), len(heads(undecided)
814 814 coreconfigitem(
815 815 b'devel',
816 816 b'discovery.grow-sample.dynamic',
817 817 default=True,
818 818 )
819 819 # discovery.grow-sample.rate control the rate at which the sample grow
820 820 coreconfigitem(
821 821 b'devel',
822 822 b'discovery.grow-sample.rate',
823 823 default=1.05,
824 824 )
825 825 # If discovery.randomize is False, random sampling during discovery are
826 826 # deterministic. It is meant for integration tests.
827 827 coreconfigitem(
828 828 b'devel',
829 829 b'discovery.randomize',
830 830 default=True,
831 831 )
832 832 # Control the initial size of the discovery sample
833 833 coreconfigitem(
834 834 b'devel',
835 835 b'discovery.sample-size',
836 836 default=200,
837 837 )
838 838 # Control the initial size of the discovery for initial change
839 839 coreconfigitem(
840 840 b'devel',
841 841 b'discovery.sample-size.initial',
842 842 default=100,
843 843 )
844 844 _registerdiffopts(section=b'diff')
845 845 coreconfigitem(
846 846 b'diff',
847 847 b'merge',
848 848 default=False,
849 849 experimental=True,
850 850 )
851 851 coreconfigitem(
852 852 b'email',
853 853 b'bcc',
854 854 default=None,
855 855 )
856 856 coreconfigitem(
857 857 b'email',
858 858 b'cc',
859 859 default=None,
860 860 )
861 861 coreconfigitem(
862 862 b'email',
863 863 b'charsets',
864 864 default=list,
865 865 )
866 866 coreconfigitem(
867 867 b'email',
868 868 b'from',
869 869 default=None,
870 870 )
871 871 coreconfigitem(
872 872 b'email',
873 873 b'method',
874 874 default=b'smtp',
875 875 )
876 876 coreconfigitem(
877 877 b'email',
878 878 b'reply-to',
879 879 default=None,
880 880 )
881 881 coreconfigitem(
882 882 b'email',
883 883 b'to',
884 884 default=None,
885 885 )
886 886 coreconfigitem(
887 887 b'experimental',
888 888 b'archivemetatemplate',
889 889 default=dynamicdefault,
890 890 )
891 891 coreconfigitem(
892 892 b'experimental',
893 893 b'auto-publish',
894 894 default=b'publish',
895 895 )
896 896 coreconfigitem(
897 897 b'experimental',
898 898 b'bundle-phases',
899 899 default=False,
900 900 )
901 901 coreconfigitem(
902 902 b'experimental',
903 903 b'bundle2-advertise',
904 904 default=True,
905 905 )
906 906 coreconfigitem(
907 907 b'experimental',
908 908 b'bundle2-output-capture',
909 909 default=False,
910 910 )
911 911 coreconfigitem(
912 912 b'experimental',
913 913 b'bundle2.pushback',
914 914 default=False,
915 915 )
916 916 coreconfigitem(
917 917 b'experimental',
918 918 b'bundle2lazylocking',
919 919 default=False,
920 920 )
921 921 coreconfigitem(
922 922 b'experimental',
923 923 b'bundlecomplevel',
924 924 default=None,
925 925 )
926 926 coreconfigitem(
927 927 b'experimental',
928 928 b'bundlecomplevel.bzip2',
929 929 default=None,
930 930 )
931 931 coreconfigitem(
932 932 b'experimental',
933 933 b'bundlecomplevel.gzip',
934 934 default=None,
935 935 )
936 936 coreconfigitem(
937 937 b'experimental',
938 938 b'bundlecomplevel.none',
939 939 default=None,
940 940 )
941 941 coreconfigitem(
942 942 b'experimental',
943 943 b'bundlecomplevel.zstd',
944 944 default=None,
945 945 )
946 946 coreconfigitem(
947 947 b'experimental',
948 948 b'bundlecompthreads',
949 949 default=None,
950 950 )
951 951 coreconfigitem(
952 952 b'experimental',
953 953 b'bundlecompthreads.bzip2',
954 954 default=None,
955 955 )
956 956 coreconfigitem(
957 957 b'experimental',
958 958 b'bundlecompthreads.gzip',
959 959 default=None,
960 960 )
961 961 coreconfigitem(
962 962 b'experimental',
963 963 b'bundlecompthreads.none',
964 964 default=None,
965 965 )
966 966 coreconfigitem(
967 967 b'experimental',
968 968 b'bundlecompthreads.zstd',
969 969 default=None,
970 970 )
971 971 coreconfigitem(
972 972 b'experimental',
973 973 b'changegroup3',
974 974 default=True,
975 975 )
976 976 coreconfigitem(
977 977 b'experimental',
978 978 b'changegroup4',
979 979 default=False,
980 980 )
981 981
982 982 # might remove rank configuration once the computation has no impact
983 983 coreconfigitem(
984 984 b'experimental',
985 985 b'changelog-v2.compute-rank',
986 986 default=True,
987 987 )
988 988 coreconfigitem(
989 989 b'experimental',
990 990 b'cleanup-as-archived',
991 991 default=False,
992 992 )
993 993 coreconfigitem(
994 994 b'experimental',
995 995 b'clientcompressionengines',
996 996 default=list,
997 997 )
998 998 coreconfigitem(
999 999 b'experimental',
1000 1000 b'copytrace',
1001 1001 default=b'on',
1002 1002 )
1003 1003 coreconfigitem(
1004 1004 b'experimental',
1005 1005 b'copytrace.movecandidateslimit',
1006 1006 default=100,
1007 1007 )
1008 1008 coreconfigitem(
1009 1009 b'experimental',
1010 1010 b'copytrace.sourcecommitlimit',
1011 1011 default=100,
1012 1012 )
1013 1013 coreconfigitem(
1014 1014 b'experimental',
1015 1015 b'copies.read-from',
1016 1016 default=b"filelog-only",
1017 1017 )
1018 1018 coreconfigitem(
1019 1019 b'experimental',
1020 1020 b'copies.write-to',
1021 1021 default=b'filelog-only',
1022 1022 )
1023 1023 coreconfigitem(
1024 1024 b'experimental',
1025 1025 b'crecordtest',
1026 1026 default=None,
1027 1027 )
1028 1028 coreconfigitem(
1029 1029 b'experimental',
1030 1030 b'directaccess',
1031 1031 default=False,
1032 1032 )
1033 1033 coreconfigitem(
1034 1034 b'experimental',
1035 1035 b'directaccess.revnums',
1036 1036 default=False,
1037 1037 )
1038 1038 coreconfigitem(
1039 1039 b'experimental',
1040 1040 b'editortmpinhg',
1041 1041 default=False,
1042 1042 )
1043 1043 coreconfigitem(
1044 1044 b'experimental',
1045 1045 b'evolution',
1046 1046 default=list,
1047 1047 )
1048 1048 coreconfigitem(
1049 1049 b'experimental',
1050 1050 b'evolution.allowdivergence',
1051 1051 default=False,
1052 1052 alias=[(b'experimental', b'allowdivergence')],
1053 1053 )
1054 1054 coreconfigitem(
1055 1055 b'experimental',
1056 1056 b'evolution.allowunstable',
1057 1057 default=None,
1058 1058 )
1059 1059 coreconfigitem(
1060 1060 b'experimental',
1061 1061 b'evolution.createmarkers',
1062 1062 default=None,
1063 1063 )
1064 1064 coreconfigitem(
1065 1065 b'experimental',
1066 1066 b'evolution.effect-flags',
1067 1067 default=True,
1068 1068 alias=[(b'experimental', b'effect-flags')],
1069 1069 )
1070 1070 coreconfigitem(
1071 1071 b'experimental',
1072 1072 b'evolution.exchange',
1073 1073 default=None,
1074 1074 )
1075 1075 coreconfigitem(
1076 1076 b'experimental',
1077 1077 b'evolution.bundle-obsmarker',
1078 1078 default=False,
1079 1079 )
1080 1080 coreconfigitem(
1081 1081 b'experimental',
1082 1082 b'evolution.bundle-obsmarker:mandatory',
1083 1083 default=True,
1084 1084 )
1085 1085 coreconfigitem(
1086 1086 b'experimental',
1087 1087 b'log.topo',
1088 1088 default=False,
1089 1089 )
1090 1090 coreconfigitem(
1091 1091 b'experimental',
1092 1092 b'evolution.report-instabilities',
1093 1093 default=True,
1094 1094 )
1095 1095 coreconfigitem(
1096 1096 b'experimental',
1097 1097 b'evolution.track-operation',
1098 1098 default=True,
1099 1099 )
1100 1100 # repo-level config to exclude a revset visibility
1101 1101 #
1102 1102 # The target use case is to use `share` to expose different subset of the same
1103 1103 # repository, especially server side. See also `server.view`.
1104 1104 coreconfigitem(
1105 1105 b'experimental',
1106 1106 b'extra-filter-revs',
1107 1107 default=None,
1108 1108 )
1109 1109 coreconfigitem(
1110 1110 b'experimental',
1111 1111 b'maxdeltachainspan',
1112 1112 default=-1,
1113 1113 )
1114 1114 # tracks files which were undeleted (merge might delete them but we explicitly
1115 1115 # kept/undeleted them) and creates new filenodes for them
1116 1116 coreconfigitem(
1117 1117 b'experimental',
1118 1118 b'merge-track-salvaged',
1119 1119 default=False,
1120 1120 )
1121 1121 coreconfigitem(
1122 1122 b'experimental',
1123 1123 b'mmapindexthreshold',
1124 1124 default=None,
1125 1125 )
1126 1126 coreconfigitem(
1127 1127 b'experimental',
1128 1128 b'narrow',
1129 1129 default=False,
1130 1130 )
1131 1131 coreconfigitem(
1132 1132 b'experimental',
1133 1133 b'nonnormalparanoidcheck',
1134 1134 default=False,
1135 1135 )
1136 1136 coreconfigitem(
1137 1137 b'experimental',
1138 1138 b'exportableenviron',
1139 1139 default=list,
1140 1140 )
1141 1141 coreconfigitem(
1142 1142 b'experimental',
1143 1143 b'extendedheader.index',
1144 1144 default=None,
1145 1145 )
1146 1146 coreconfigitem(
1147 1147 b'experimental',
1148 1148 b'extendedheader.similarity',
1149 1149 default=False,
1150 1150 )
1151 1151 coreconfigitem(
1152 1152 b'experimental',
1153 1153 b'graphshorten',
1154 1154 default=False,
1155 1155 )
1156 1156 coreconfigitem(
1157 1157 b'experimental',
1158 1158 b'graphstyle.parent',
1159 1159 default=dynamicdefault,
1160 1160 )
1161 1161 coreconfigitem(
1162 1162 b'experimental',
1163 1163 b'graphstyle.missing',
1164 1164 default=dynamicdefault,
1165 1165 )
1166 1166 coreconfigitem(
1167 1167 b'experimental',
1168 1168 b'graphstyle.grandparent',
1169 1169 default=dynamicdefault,
1170 1170 )
1171 1171 coreconfigitem(
1172 1172 b'experimental',
1173 1173 b'hook-track-tags',
1174 1174 default=False,
1175 1175 )
1176 1176 coreconfigitem(
1177 1177 b'experimental',
1178 1178 b'httppostargs',
1179 1179 default=False,
1180 1180 )
1181 1181 coreconfigitem(b'experimental', b'nointerrupt', default=False)
1182 1182 coreconfigitem(b'experimental', b'nointerrupt-interactiveonly', default=True)
1183 1183
1184 1184 coreconfigitem(
1185 1185 b'experimental',
1186 1186 b'obsmarkers-exchange-debug',
1187 1187 default=False,
1188 1188 )
1189 1189 coreconfigitem(
1190 1190 b'experimental',
1191 1191 b'remotenames',
1192 1192 default=False,
1193 1193 )
1194 1194 coreconfigitem(
1195 1195 b'experimental',
1196 1196 b'removeemptydirs',
1197 1197 default=True,
1198 1198 )
1199 1199 coreconfigitem(
1200 1200 b'experimental',
1201 1201 b'revert.interactive.select-to-keep',
1202 1202 default=False,
1203 1203 )
1204 1204 coreconfigitem(
1205 1205 b'experimental',
1206 1206 b'revisions.prefixhexnode',
1207 1207 default=False,
1208 1208 )
1209 1209 # "out of experimental" todo list.
1210 1210 #
1211 1211 # * include management of a persistent nodemap in the main docket
1212 1212 # * enforce a "no-truncate" policy for mmap safety
1213 1213 # - for censoring operation
1214 1214 # - for stripping operation
1215 1215 # - for rollback operation
1216 1216 # * proper streaming (race free) of the docket file
1217 1217 # * track garbage data to evemtually allow rewriting -existing- sidedata.
1218 1218 # * Exchange-wise, we will also need to do something more efficient than
1219 1219 # keeping references to the affected revlogs, especially memory-wise when
1220 1220 # rewriting sidedata.
1221 1221 # * introduce a proper solution to reduce the number of filelog related files.
1222 1222 # * use caching for reading sidedata (similar to what we do for data).
1223 1223 # * no longer set offset=0 if sidedata_size=0 (simplify cutoff computation).
1224 1224 # * Improvement to consider
1225 1225 # - avoid compression header in chunk using the default compression?
1226 1226 # - forbid "inline" compression mode entirely?
1227 1227 # - split the data offset and flag field (the 2 bytes save are mostly trouble)
1228 1228 # - keep track of uncompressed -chunk- size (to preallocate memory better)
1229 1229 # - keep track of chain base or size (probably not that useful anymore)
1230 1230 coreconfigitem(
1231 1231 b'experimental',
1232 1232 b'revlogv2',
1233 1233 default=None,
1234 1234 )
1235 1235 coreconfigitem(
1236 1236 b'experimental',
1237 1237 b'revisions.disambiguatewithin',
1238 1238 default=None,
1239 1239 )
1240 1240 coreconfigitem(
1241 1241 b'experimental',
1242 1242 b'rust.index',
1243 1243 default=False,
1244 1244 )
1245 1245 coreconfigitem(
1246 1246 b'experimental',
1247 b'server.allow-hidden-access',
1248 default=list,
1249 )
1250 coreconfigitem(
1251 b'experimental',
1247 1252 b'server.filesdata.recommended-batch-size',
1248 1253 default=50000,
1249 1254 )
1250 1255 coreconfigitem(
1251 1256 b'experimental',
1252 1257 b'server.manifestdata.recommended-batch-size',
1253 1258 default=100000,
1254 1259 )
1255 1260 coreconfigitem(
1256 1261 b'experimental',
1257 1262 b'server.stream-narrow-clones',
1258 1263 default=False,
1259 1264 )
1260 1265 coreconfigitem(
1261 1266 b'experimental',
1262 1267 b'single-head-per-branch',
1263 1268 default=False,
1264 1269 )
1265 1270 coreconfigitem(
1266 1271 b'experimental',
1267 1272 b'single-head-per-branch:account-closed-heads',
1268 1273 default=False,
1269 1274 )
1270 1275 coreconfigitem(
1271 1276 b'experimental',
1272 1277 b'single-head-per-branch:public-changes-only',
1273 1278 default=False,
1274 1279 )
1275 1280 coreconfigitem(
1276 1281 b'experimental',
1277 1282 b'sparse-read',
1278 1283 default=False,
1279 1284 )
1280 1285 coreconfigitem(
1281 1286 b'experimental',
1282 1287 b'sparse-read.density-threshold',
1283 1288 default=0.50,
1284 1289 )
1285 1290 coreconfigitem(
1286 1291 b'experimental',
1287 1292 b'sparse-read.min-gap-size',
1288 1293 default=b'65K',
1289 1294 )
1290 1295 coreconfigitem(
1291 1296 b'experimental',
1292 1297 b'treemanifest',
1293 1298 default=False,
1294 1299 )
1295 1300 coreconfigitem(
1296 1301 b'experimental',
1297 1302 b'update.atomic-file',
1298 1303 default=False,
1299 1304 )
1300 1305 coreconfigitem(
1301 1306 b'experimental',
1302 1307 b'web.full-garbage-collection-rate',
1303 1308 default=1, # still forcing a full collection on each request
1304 1309 )
1305 1310 coreconfigitem(
1306 1311 b'experimental',
1307 1312 b'worker.wdir-get-thread-safe',
1308 1313 default=False,
1309 1314 )
1310 1315 coreconfigitem(
1311 1316 b'experimental',
1312 1317 b'worker.repository-upgrade',
1313 1318 default=False,
1314 1319 )
1315 1320 coreconfigitem(
1316 1321 b'experimental',
1317 1322 b'xdiff',
1318 1323 default=False,
1319 1324 )
1320 1325 coreconfigitem(
1321 1326 b'extensions',
1322 1327 b'[^:]*',
1323 1328 default=None,
1324 1329 generic=True,
1325 1330 )
1326 1331 coreconfigitem(
1327 1332 b'extensions',
1328 1333 b'[^:]*:required',
1329 1334 default=False,
1330 1335 generic=True,
1331 1336 )
1332 1337 coreconfigitem(
1333 1338 b'extdata',
1334 1339 b'.*',
1335 1340 default=None,
1336 1341 generic=True,
1337 1342 )
1338 1343 coreconfigitem(
1339 1344 b'format',
1340 1345 b'bookmarks-in-store',
1341 1346 default=False,
1342 1347 )
1343 1348 coreconfigitem(
1344 1349 b'format',
1345 1350 b'chunkcachesize',
1346 1351 default=None,
1347 1352 experimental=True,
1348 1353 )
1349 1354 coreconfigitem(
1350 1355 # Enable this dirstate format *when creating a new repository*.
1351 1356 # Which format to use for existing repos is controlled by .hg/requires
1352 1357 b'format',
1353 1358 b'use-dirstate-v2',
1354 1359 default=False,
1355 1360 experimental=True,
1356 1361 alias=[(b'format', b'exp-rc-dirstate-v2')],
1357 1362 )
1358 1363 coreconfigitem(
1359 1364 b'format',
1360 1365 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories',
1361 1366 default=False,
1362 1367 experimental=True,
1363 1368 )
1364 1369 coreconfigitem(
1365 1370 b'format',
1366 1371 b'use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet',
1367 1372 default=False,
1368 1373 experimental=True,
1369 1374 )
1370 1375 coreconfigitem(
1371 1376 b'format',
1372 1377 b'use-dirstate-tracked-hint',
1373 1378 default=False,
1374 1379 experimental=True,
1375 1380 )
1376 1381 coreconfigitem(
1377 1382 b'format',
1378 1383 b'use-dirstate-tracked-hint.version',
1379 1384 default=1,
1380 1385 experimental=True,
1381 1386 )
1382 1387 coreconfigitem(
1383 1388 b'format',
1384 1389 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories',
1385 1390 default=False,
1386 1391 experimental=True,
1387 1392 )
1388 1393 coreconfigitem(
1389 1394 b'format',
1390 1395 b'use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet',
1391 1396 default=False,
1392 1397 experimental=True,
1393 1398 )
1394 1399 coreconfigitem(
1395 1400 b'format',
1396 1401 b'dotencode',
1397 1402 default=True,
1398 1403 )
1399 1404 coreconfigitem(
1400 1405 b'format',
1401 1406 b'generaldelta',
1402 1407 default=False,
1403 1408 experimental=True,
1404 1409 )
1405 1410 coreconfigitem(
1406 1411 b'format',
1407 1412 b'manifestcachesize',
1408 1413 default=None,
1409 1414 experimental=True,
1410 1415 )
1411 1416 coreconfigitem(
1412 1417 b'format',
1413 1418 b'maxchainlen',
1414 1419 default=dynamicdefault,
1415 1420 experimental=True,
1416 1421 )
1417 1422 coreconfigitem(
1418 1423 b'format',
1419 1424 b'obsstore-version',
1420 1425 default=None,
1421 1426 )
1422 1427 coreconfigitem(
1423 1428 b'format',
1424 1429 b'sparse-revlog',
1425 1430 default=True,
1426 1431 )
1427 1432 coreconfigitem(
1428 1433 b'format',
1429 1434 b'revlog-compression',
1430 1435 default=lambda: [b'zstd', b'zlib'],
1431 1436 alias=[(b'experimental', b'format.compression')],
1432 1437 )
1433 1438 # Experimental TODOs:
1434 1439 #
1435 1440 # * Same as for revlogv2 (but for the reduction of the number of files)
1436 1441 # * Actually computing the rank of changesets
1437 1442 # * Improvement to investigate
1438 1443 # - storing .hgtags fnode
1439 1444 # - storing branch related identifier
1440 1445
1441 1446 coreconfigitem(
1442 1447 b'format',
1443 1448 b'exp-use-changelog-v2',
1444 1449 default=None,
1445 1450 experimental=True,
1446 1451 )
1447 1452 coreconfigitem(
1448 1453 b'format',
1449 1454 b'usefncache',
1450 1455 default=True,
1451 1456 )
1452 1457 coreconfigitem(
1453 1458 b'format',
1454 1459 b'usegeneraldelta',
1455 1460 default=True,
1456 1461 )
1457 1462 coreconfigitem(
1458 1463 b'format',
1459 1464 b'usestore',
1460 1465 default=True,
1461 1466 )
1462 1467
1463 1468
1464 1469 def _persistent_nodemap_default():
1465 1470 """compute `use-persistent-nodemap` default value
1466 1471
1467 1472 The feature is disabled unless a fast implementation is available.
1468 1473 """
1469 1474 from . import policy
1470 1475
1471 1476 return policy.importrust('revlog') is not None
1472 1477
1473 1478
1474 1479 coreconfigitem(
1475 1480 b'format',
1476 1481 b'use-persistent-nodemap',
1477 1482 default=_persistent_nodemap_default,
1478 1483 )
1479 1484 coreconfigitem(
1480 1485 b'format',
1481 1486 b'exp-use-copies-side-data-changeset',
1482 1487 default=False,
1483 1488 experimental=True,
1484 1489 )
1485 1490 coreconfigitem(
1486 1491 b'format',
1487 1492 b'use-share-safe',
1488 1493 default=True,
1489 1494 )
1490 1495 coreconfigitem(
1491 1496 b'format',
1492 1497 b'use-share-safe.automatic-upgrade-of-mismatching-repositories',
1493 1498 default=False,
1494 1499 experimental=True,
1495 1500 )
1496 1501 coreconfigitem(
1497 1502 b'format',
1498 1503 b'use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet',
1499 1504 default=False,
1500 1505 experimental=True,
1501 1506 )
1502 1507
1503 1508 # Moving this on by default means we are confident about the scaling of phases.
1504 1509 # This is not garanteed to be the case at the time this message is written.
1505 1510 coreconfigitem(
1506 1511 b'format',
1507 1512 b'use-internal-phase',
1508 1513 default=False,
1509 1514 experimental=True,
1510 1515 )
1511 1516 # The interaction between the archived phase and obsolescence markers needs to
1512 1517 # be sorted out before wider usage of this are to be considered.
1513 1518 #
1514 1519 # At the time this message is written, behavior when archiving obsolete
1515 1520 # changeset differ significantly from stripping. As part of stripping, we also
1516 1521 # remove the obsolescence marker associated to the stripped changesets,
1517 1522 # revealing the precedecessors changesets when applicable. When archiving, we
1518 1523 # don't touch the obsolescence markers, keeping everything hidden. This can
1519 1524 # result in quite confusing situation for people combining exchanging draft
1520 1525 # with the archived phases. As some markers needed by others may be skipped
1521 1526 # during exchange.
1522 1527 coreconfigitem(
1523 1528 b'format',
1524 1529 b'exp-archived-phase',
1525 1530 default=False,
1526 1531 experimental=True,
1527 1532 )
1528 1533 coreconfigitem(
1529 1534 b'shelve',
1530 1535 b'store',
1531 1536 default=b'internal',
1532 1537 experimental=True,
1533 1538 )
1534 1539 coreconfigitem(
1535 1540 b'fsmonitor',
1536 1541 b'warn_when_unused',
1537 1542 default=True,
1538 1543 )
1539 1544 coreconfigitem(
1540 1545 b'fsmonitor',
1541 1546 b'warn_update_file_count',
1542 1547 default=50000,
1543 1548 )
1544 1549 coreconfigitem(
1545 1550 b'fsmonitor',
1546 1551 b'warn_update_file_count_rust',
1547 1552 default=400000,
1548 1553 )
1549 1554 coreconfigitem(
1550 1555 b'help',
1551 1556 br'hidden-command\..*',
1552 1557 default=False,
1553 1558 generic=True,
1554 1559 )
1555 1560 coreconfigitem(
1556 1561 b'help',
1557 1562 br'hidden-topic\..*',
1558 1563 default=False,
1559 1564 generic=True,
1560 1565 )
1561 1566 coreconfigitem(
1562 1567 b'hooks',
1563 1568 b'[^:]*',
1564 1569 default=dynamicdefault,
1565 1570 generic=True,
1566 1571 )
1567 1572 coreconfigitem(
1568 1573 b'hooks',
1569 1574 b'.*:run-with-plain',
1570 1575 default=True,
1571 1576 generic=True,
1572 1577 )
1573 1578 coreconfigitem(
1574 1579 b'hgweb-paths',
1575 1580 b'.*',
1576 1581 default=list,
1577 1582 generic=True,
1578 1583 )
1579 1584 coreconfigitem(
1580 1585 b'hostfingerprints',
1581 1586 b'.*',
1582 1587 default=list,
1583 1588 generic=True,
1584 1589 )
1585 1590 coreconfigitem(
1586 1591 b'hostsecurity',
1587 1592 b'ciphers',
1588 1593 default=None,
1589 1594 )
1590 1595 coreconfigitem(
1591 1596 b'hostsecurity',
1592 1597 b'minimumprotocol',
1593 1598 default=dynamicdefault,
1594 1599 )
1595 1600 coreconfigitem(
1596 1601 b'hostsecurity',
1597 1602 b'.*:minimumprotocol$',
1598 1603 default=dynamicdefault,
1599 1604 generic=True,
1600 1605 )
1601 1606 coreconfigitem(
1602 1607 b'hostsecurity',
1603 1608 b'.*:ciphers$',
1604 1609 default=dynamicdefault,
1605 1610 generic=True,
1606 1611 )
1607 1612 coreconfigitem(
1608 1613 b'hostsecurity',
1609 1614 b'.*:fingerprints$',
1610 1615 default=list,
1611 1616 generic=True,
1612 1617 )
1613 1618 coreconfigitem(
1614 1619 b'hostsecurity',
1615 1620 b'.*:verifycertsfile$',
1616 1621 default=None,
1617 1622 generic=True,
1618 1623 )
1619 1624
1620 1625 coreconfigitem(
1621 1626 b'http_proxy',
1622 1627 b'always',
1623 1628 default=False,
1624 1629 )
1625 1630 coreconfigitem(
1626 1631 b'http_proxy',
1627 1632 b'host',
1628 1633 default=None,
1629 1634 )
1630 1635 coreconfigitem(
1631 1636 b'http_proxy',
1632 1637 b'no',
1633 1638 default=list,
1634 1639 )
1635 1640 coreconfigitem(
1636 1641 b'http_proxy',
1637 1642 b'passwd',
1638 1643 default=None,
1639 1644 )
1640 1645 coreconfigitem(
1641 1646 b'http_proxy',
1642 1647 b'user',
1643 1648 default=None,
1644 1649 )
1645 1650
1646 1651 coreconfigitem(
1647 1652 b'http',
1648 1653 b'timeout',
1649 1654 default=None,
1650 1655 )
1651 1656
1652 1657 coreconfigitem(
1653 1658 b'logtoprocess',
1654 1659 b'commandexception',
1655 1660 default=None,
1656 1661 )
1657 1662 coreconfigitem(
1658 1663 b'logtoprocess',
1659 1664 b'commandfinish',
1660 1665 default=None,
1661 1666 )
1662 1667 coreconfigitem(
1663 1668 b'logtoprocess',
1664 1669 b'command',
1665 1670 default=None,
1666 1671 )
1667 1672 coreconfigitem(
1668 1673 b'logtoprocess',
1669 1674 b'develwarn',
1670 1675 default=None,
1671 1676 )
1672 1677 coreconfigitem(
1673 1678 b'logtoprocess',
1674 1679 b'uiblocked',
1675 1680 default=None,
1676 1681 )
1677 1682 coreconfigitem(
1678 1683 b'merge',
1679 1684 b'checkunknown',
1680 1685 default=b'abort',
1681 1686 )
1682 1687 coreconfigitem(
1683 1688 b'merge',
1684 1689 b'checkignored',
1685 1690 default=b'abort',
1686 1691 )
1687 1692 coreconfigitem(
1688 1693 b'experimental',
1689 1694 b'merge.checkpathconflicts',
1690 1695 default=False,
1691 1696 )
1692 1697 coreconfigitem(
1693 1698 b'merge',
1694 1699 b'followcopies',
1695 1700 default=True,
1696 1701 )
1697 1702 coreconfigitem(
1698 1703 b'merge',
1699 1704 b'on-failure',
1700 1705 default=b'continue',
1701 1706 )
1702 1707 coreconfigitem(
1703 1708 b'merge',
1704 1709 b'preferancestor',
1705 1710 default=lambda: [b'*'],
1706 1711 experimental=True,
1707 1712 )
1708 1713 coreconfigitem(
1709 1714 b'merge',
1710 1715 b'strict-capability-check',
1711 1716 default=False,
1712 1717 )
1713 1718 coreconfigitem(
1714 1719 b'merge',
1715 1720 b'disable-partial-tools',
1716 1721 default=False,
1717 1722 experimental=True,
1718 1723 )
1719 1724 coreconfigitem(
1720 1725 b'partial-merge-tools',
1721 1726 b'.*',
1722 1727 default=None,
1723 1728 generic=True,
1724 1729 experimental=True,
1725 1730 )
1726 1731 coreconfigitem(
1727 1732 b'partial-merge-tools',
1728 1733 br'.*\.patterns',
1729 1734 default=dynamicdefault,
1730 1735 generic=True,
1731 1736 priority=-1,
1732 1737 experimental=True,
1733 1738 )
1734 1739 coreconfigitem(
1735 1740 b'partial-merge-tools',
1736 1741 br'.*\.executable$',
1737 1742 default=dynamicdefault,
1738 1743 generic=True,
1739 1744 priority=-1,
1740 1745 experimental=True,
1741 1746 )
1742 1747 coreconfigitem(
1743 1748 b'partial-merge-tools',
1744 1749 br'.*\.order',
1745 1750 default=0,
1746 1751 generic=True,
1747 1752 priority=-1,
1748 1753 experimental=True,
1749 1754 )
1750 1755 coreconfigitem(
1751 1756 b'partial-merge-tools',
1752 1757 br'.*\.args',
1753 1758 default=b"$local $base $other",
1754 1759 generic=True,
1755 1760 priority=-1,
1756 1761 experimental=True,
1757 1762 )
1758 1763 coreconfigitem(
1759 1764 b'partial-merge-tools',
1760 1765 br'.*\.disable',
1761 1766 default=False,
1762 1767 generic=True,
1763 1768 priority=-1,
1764 1769 experimental=True,
1765 1770 )
1766 1771 coreconfigitem(
1767 1772 b'merge-tools',
1768 1773 b'.*',
1769 1774 default=None,
1770 1775 generic=True,
1771 1776 )
1772 1777 coreconfigitem(
1773 1778 b'merge-tools',
1774 1779 br'.*\.args$',
1775 1780 default=b"$local $base $other",
1776 1781 generic=True,
1777 1782 priority=-1,
1778 1783 )
1779 1784 coreconfigitem(
1780 1785 b'merge-tools',
1781 1786 br'.*\.binary$',
1782 1787 default=False,
1783 1788 generic=True,
1784 1789 priority=-1,
1785 1790 )
1786 1791 coreconfigitem(
1787 1792 b'merge-tools',
1788 1793 br'.*\.check$',
1789 1794 default=list,
1790 1795 generic=True,
1791 1796 priority=-1,
1792 1797 )
1793 1798 coreconfigitem(
1794 1799 b'merge-tools',
1795 1800 br'.*\.checkchanged$',
1796 1801 default=False,
1797 1802 generic=True,
1798 1803 priority=-1,
1799 1804 )
1800 1805 coreconfigitem(
1801 1806 b'merge-tools',
1802 1807 br'.*\.executable$',
1803 1808 default=dynamicdefault,
1804 1809 generic=True,
1805 1810 priority=-1,
1806 1811 )
1807 1812 coreconfigitem(
1808 1813 b'merge-tools',
1809 1814 br'.*\.fixeol$',
1810 1815 default=False,
1811 1816 generic=True,
1812 1817 priority=-1,
1813 1818 )
1814 1819 coreconfigitem(
1815 1820 b'merge-tools',
1816 1821 br'.*\.gui$',
1817 1822 default=False,
1818 1823 generic=True,
1819 1824 priority=-1,
1820 1825 )
1821 1826 coreconfigitem(
1822 1827 b'merge-tools',
1823 1828 br'.*\.mergemarkers$',
1824 1829 default=b'basic',
1825 1830 generic=True,
1826 1831 priority=-1,
1827 1832 )
1828 1833 coreconfigitem(
1829 1834 b'merge-tools',
1830 1835 br'.*\.mergemarkertemplate$',
1831 1836 default=dynamicdefault, # take from command-templates.mergemarker
1832 1837 generic=True,
1833 1838 priority=-1,
1834 1839 )
1835 1840 coreconfigitem(
1836 1841 b'merge-tools',
1837 1842 br'.*\.priority$',
1838 1843 default=0,
1839 1844 generic=True,
1840 1845 priority=-1,
1841 1846 )
1842 1847 coreconfigitem(
1843 1848 b'merge-tools',
1844 1849 br'.*\.premerge$',
1845 1850 default=dynamicdefault,
1846 1851 generic=True,
1847 1852 priority=-1,
1848 1853 )
1849 1854 coreconfigitem(
1850 1855 b'merge-tools',
1851 1856 br'.*\.regappend$',
1852 1857 default=b"",
1853 1858 generic=True,
1854 1859 priority=-1,
1855 1860 )
1856 1861 coreconfigitem(
1857 1862 b'merge-tools',
1858 1863 br'.*\.symlink$',
1859 1864 default=False,
1860 1865 generic=True,
1861 1866 priority=-1,
1862 1867 )
1863 1868 coreconfigitem(
1864 1869 b'pager',
1865 1870 b'attend-.*',
1866 1871 default=dynamicdefault,
1867 1872 generic=True,
1868 1873 )
1869 1874 coreconfigitem(
1870 1875 b'pager',
1871 1876 b'ignore',
1872 1877 default=list,
1873 1878 )
1874 1879 coreconfigitem(
1875 1880 b'pager',
1876 1881 b'pager',
1877 1882 default=dynamicdefault,
1878 1883 )
1879 1884 coreconfigitem(
1880 1885 b'patch',
1881 1886 b'eol',
1882 1887 default=b'strict',
1883 1888 )
1884 1889 coreconfigitem(
1885 1890 b'patch',
1886 1891 b'fuzz',
1887 1892 default=2,
1888 1893 )
1889 1894 coreconfigitem(
1890 1895 b'paths',
1891 1896 b'default',
1892 1897 default=None,
1893 1898 )
1894 1899 coreconfigitem(
1895 1900 b'paths',
1896 1901 b'default-push',
1897 1902 default=None,
1898 1903 )
1899 1904 coreconfigitem(
1900 1905 b'paths',
1901 1906 b'[^:]*',
1902 1907 default=None,
1903 1908 generic=True,
1904 1909 )
1905 1910 coreconfigitem(
1906 1911 b'paths',
1907 1912 b'.*:bookmarks.mode',
1908 1913 default='default',
1909 1914 generic=True,
1910 1915 )
1911 1916 coreconfigitem(
1912 1917 b'paths',
1913 1918 b'.*:multi-urls',
1914 1919 default=False,
1915 1920 generic=True,
1916 1921 )
1917 1922 coreconfigitem(
1918 1923 b'paths',
1919 1924 b'.*:pushrev',
1920 1925 default=None,
1921 1926 generic=True,
1922 1927 )
1923 1928 coreconfigitem(
1924 1929 b'paths',
1925 1930 b'.*:pushurl',
1926 1931 default=None,
1927 1932 generic=True,
1928 1933 )
1929 1934 coreconfigitem(
1930 1935 b'paths',
1931 1936 b'.*:pulled-delta-reuse-policy',
1932 1937 default=None,
1933 1938 generic=True,
1934 1939 )
1935 1940 coreconfigitem(
1936 1941 b'phases',
1937 1942 b'checksubrepos',
1938 1943 default=b'follow',
1939 1944 )
1940 1945 coreconfigitem(
1941 1946 b'phases',
1942 1947 b'new-commit',
1943 1948 default=b'draft',
1944 1949 )
1945 1950 coreconfigitem(
1946 1951 b'phases',
1947 1952 b'publish',
1948 1953 default=True,
1949 1954 )
1950 1955 coreconfigitem(
1951 1956 b'profiling',
1952 1957 b'enabled',
1953 1958 default=False,
1954 1959 )
1955 1960 coreconfigitem(
1956 1961 b'profiling',
1957 1962 b'format',
1958 1963 default=b'text',
1959 1964 )
1960 1965 coreconfigitem(
1961 1966 b'profiling',
1962 1967 b'freq',
1963 1968 default=1000,
1964 1969 )
1965 1970 coreconfigitem(
1966 1971 b'profiling',
1967 1972 b'limit',
1968 1973 default=30,
1969 1974 )
1970 1975 coreconfigitem(
1971 1976 b'profiling',
1972 1977 b'nested',
1973 1978 default=0,
1974 1979 )
1975 1980 coreconfigitem(
1976 1981 b'profiling',
1977 1982 b'output',
1978 1983 default=None,
1979 1984 )
1980 1985 coreconfigitem(
1981 1986 b'profiling',
1982 1987 b'showmax',
1983 1988 default=0.999,
1984 1989 )
1985 1990 coreconfigitem(
1986 1991 b'profiling',
1987 1992 b'showmin',
1988 1993 default=dynamicdefault,
1989 1994 )
1990 1995 coreconfigitem(
1991 1996 b'profiling',
1992 1997 b'showtime',
1993 1998 default=True,
1994 1999 )
1995 2000 coreconfigitem(
1996 2001 b'profiling',
1997 2002 b'sort',
1998 2003 default=b'inlinetime',
1999 2004 )
2000 2005 coreconfigitem(
2001 2006 b'profiling',
2002 2007 b'statformat',
2003 2008 default=b'hotpath',
2004 2009 )
2005 2010 coreconfigitem(
2006 2011 b'profiling',
2007 2012 b'time-track',
2008 2013 default=dynamicdefault,
2009 2014 )
2010 2015 coreconfigitem(
2011 2016 b'profiling',
2012 2017 b'type',
2013 2018 default=b'stat',
2014 2019 )
2015 2020 coreconfigitem(
2016 2021 b'progress',
2017 2022 b'assume-tty',
2018 2023 default=False,
2019 2024 )
2020 2025 coreconfigitem(
2021 2026 b'progress',
2022 2027 b'changedelay',
2023 2028 default=1,
2024 2029 )
2025 2030 coreconfigitem(
2026 2031 b'progress',
2027 2032 b'clear-complete',
2028 2033 default=True,
2029 2034 )
2030 2035 coreconfigitem(
2031 2036 b'progress',
2032 2037 b'debug',
2033 2038 default=False,
2034 2039 )
2035 2040 coreconfigitem(
2036 2041 b'progress',
2037 2042 b'delay',
2038 2043 default=3,
2039 2044 )
2040 2045 coreconfigitem(
2041 2046 b'progress',
2042 2047 b'disable',
2043 2048 default=False,
2044 2049 )
2045 2050 coreconfigitem(
2046 2051 b'progress',
2047 2052 b'estimateinterval',
2048 2053 default=60.0,
2049 2054 )
2050 2055 coreconfigitem(
2051 2056 b'progress',
2052 2057 b'format',
2053 2058 default=lambda: [b'topic', b'bar', b'number', b'estimate'],
2054 2059 )
2055 2060 coreconfigitem(
2056 2061 b'progress',
2057 2062 b'refresh',
2058 2063 default=0.1,
2059 2064 )
2060 2065 coreconfigitem(
2061 2066 b'progress',
2062 2067 b'width',
2063 2068 default=dynamicdefault,
2064 2069 )
2065 2070 coreconfigitem(
2066 2071 b'pull',
2067 2072 b'confirm',
2068 2073 default=False,
2069 2074 )
2070 2075 coreconfigitem(
2071 2076 b'push',
2072 2077 b'pushvars.server',
2073 2078 default=False,
2074 2079 )
2075 2080 coreconfigitem(
2076 2081 b'rewrite',
2077 2082 b'backup-bundle',
2078 2083 default=True,
2079 2084 alias=[(b'ui', b'history-editing-backup')],
2080 2085 )
2081 2086 coreconfigitem(
2082 2087 b'rewrite',
2083 2088 b'update-timestamp',
2084 2089 default=False,
2085 2090 )
2086 2091 coreconfigitem(
2087 2092 b'rewrite',
2088 2093 b'empty-successor',
2089 2094 default=b'skip',
2090 2095 experimental=True,
2091 2096 )
2092 2097 # experimental as long as format.use-dirstate-v2 is.
2093 2098 coreconfigitem(
2094 2099 b'storage',
2095 2100 b'dirstate-v2.slow-path',
2096 2101 default=b"abort",
2097 2102 experimental=True,
2098 2103 )
2099 2104 coreconfigitem(
2100 2105 b'storage',
2101 2106 b'new-repo-backend',
2102 2107 default=b'revlogv1',
2103 2108 experimental=True,
2104 2109 )
2105 2110 coreconfigitem(
2106 2111 b'storage',
2107 2112 b'revlog.optimize-delta-parent-choice',
2108 2113 default=True,
2109 2114 alias=[(b'format', b'aggressivemergedeltas')],
2110 2115 )
2111 2116 coreconfigitem(
2112 2117 b'storage',
2113 2118 b'revlog.delta-parent-search.candidate-group-chunk-size',
2114 2119 default=20,
2115 2120 )
2116 2121 coreconfigitem(
2117 2122 b'storage',
2118 2123 b'revlog.issue6528.fix-incoming',
2119 2124 default=True,
2120 2125 )
2121 2126 # experimental as long as rust is experimental (or a C version is implemented)
2122 2127 coreconfigitem(
2123 2128 b'storage',
2124 2129 b'revlog.persistent-nodemap.mmap',
2125 2130 default=True,
2126 2131 )
2127 2132 # experimental as long as format.use-persistent-nodemap is.
2128 2133 coreconfigitem(
2129 2134 b'storage',
2130 2135 b'revlog.persistent-nodemap.slow-path',
2131 2136 default=b"abort",
2132 2137 )
2133 2138
2134 2139 coreconfigitem(
2135 2140 b'storage',
2136 2141 b'revlog.reuse-external-delta',
2137 2142 default=True,
2138 2143 )
2139 2144 # This option is True unless `format.generaldelta` is set.
2140 2145 coreconfigitem(
2141 2146 b'storage',
2142 2147 b'revlog.reuse-external-delta-parent',
2143 2148 default=None,
2144 2149 )
2145 2150 coreconfigitem(
2146 2151 b'storage',
2147 2152 b'revlog.zlib.level',
2148 2153 default=None,
2149 2154 )
2150 2155 coreconfigitem(
2151 2156 b'storage',
2152 2157 b'revlog.zstd.level',
2153 2158 default=None,
2154 2159 )
2155 2160 coreconfigitem(
2156 2161 b'server',
2157 2162 b'bookmarks-pushkey-compat',
2158 2163 default=True,
2159 2164 )
2160 2165 coreconfigitem(
2161 2166 b'server',
2162 2167 b'bundle1',
2163 2168 default=True,
2164 2169 )
2165 2170 coreconfigitem(
2166 2171 b'server',
2167 2172 b'bundle1gd',
2168 2173 default=None,
2169 2174 )
2170 2175 coreconfigitem(
2171 2176 b'server',
2172 2177 b'bundle1.pull',
2173 2178 default=None,
2174 2179 )
2175 2180 coreconfigitem(
2176 2181 b'server',
2177 2182 b'bundle1gd.pull',
2178 2183 default=None,
2179 2184 )
2180 2185 coreconfigitem(
2181 2186 b'server',
2182 2187 b'bundle1.push',
2183 2188 default=None,
2184 2189 )
2185 2190 coreconfigitem(
2186 2191 b'server',
2187 2192 b'bundle1gd.push',
2188 2193 default=None,
2189 2194 )
2190 2195 coreconfigitem(
2191 2196 b'server',
2192 2197 b'bundle2.stream',
2193 2198 default=True,
2194 2199 alias=[(b'experimental', b'bundle2.stream')],
2195 2200 )
2196 2201 coreconfigitem(
2197 2202 b'server',
2198 2203 b'compressionengines',
2199 2204 default=list,
2200 2205 )
2201 2206 coreconfigitem(
2202 2207 b'server',
2203 2208 b'concurrent-push-mode',
2204 2209 default=b'check-related',
2205 2210 )
2206 2211 coreconfigitem(
2207 2212 b'server',
2208 2213 b'disablefullbundle',
2209 2214 default=False,
2210 2215 )
2211 2216 coreconfigitem(
2212 2217 b'server',
2213 2218 b'maxhttpheaderlen',
2214 2219 default=1024,
2215 2220 )
2216 2221 coreconfigitem(
2217 2222 b'server',
2218 2223 b'pullbundle',
2219 2224 default=True,
2220 2225 )
2221 2226 coreconfigitem(
2222 2227 b'server',
2223 2228 b'preferuncompressed',
2224 2229 default=False,
2225 2230 )
2226 2231 coreconfigitem(
2227 2232 b'server',
2228 2233 b'streamunbundle',
2229 2234 default=False,
2230 2235 )
2231 2236 coreconfigitem(
2232 2237 b'server',
2233 2238 b'uncompressed',
2234 2239 default=True,
2235 2240 )
2236 2241 coreconfigitem(
2237 2242 b'server',
2238 2243 b'uncompressedallowsecret',
2239 2244 default=False,
2240 2245 )
2241 2246 coreconfigitem(
2242 2247 b'server',
2243 2248 b'view',
2244 2249 default=b'served',
2245 2250 )
2246 2251 coreconfigitem(
2247 2252 b'server',
2248 2253 b'validate',
2249 2254 default=False,
2250 2255 )
2251 2256 coreconfigitem(
2252 2257 b'server',
2253 2258 b'zliblevel',
2254 2259 default=-1,
2255 2260 )
2256 2261 coreconfigitem(
2257 2262 b'server',
2258 2263 b'zstdlevel',
2259 2264 default=3,
2260 2265 )
2261 2266 coreconfigitem(
2262 2267 b'share',
2263 2268 b'pool',
2264 2269 default=None,
2265 2270 )
2266 2271 coreconfigitem(
2267 2272 b'share',
2268 2273 b'poolnaming',
2269 2274 default=b'identity',
2270 2275 )
2271 2276 coreconfigitem(
2272 2277 b'share',
2273 2278 b'safe-mismatch.source-not-safe',
2274 2279 default=b'abort',
2275 2280 )
2276 2281 coreconfigitem(
2277 2282 b'share',
2278 2283 b'safe-mismatch.source-safe',
2279 2284 default=b'abort',
2280 2285 )
2281 2286 coreconfigitem(
2282 2287 b'share',
2283 2288 b'safe-mismatch.source-not-safe.warn',
2284 2289 default=True,
2285 2290 )
2286 2291 coreconfigitem(
2287 2292 b'share',
2288 2293 b'safe-mismatch.source-safe.warn',
2289 2294 default=True,
2290 2295 )
2291 2296 coreconfigitem(
2292 2297 b'share',
2293 2298 b'safe-mismatch.source-not-safe:verbose-upgrade',
2294 2299 default=True,
2295 2300 )
2296 2301 coreconfigitem(
2297 2302 b'share',
2298 2303 b'safe-mismatch.source-safe:verbose-upgrade',
2299 2304 default=True,
2300 2305 )
2301 2306 coreconfigitem(
2302 2307 b'shelve',
2303 2308 b'maxbackups',
2304 2309 default=10,
2305 2310 )
2306 2311 coreconfigitem(
2307 2312 b'smtp',
2308 2313 b'host',
2309 2314 default=None,
2310 2315 )
2311 2316 coreconfigitem(
2312 2317 b'smtp',
2313 2318 b'local_hostname',
2314 2319 default=None,
2315 2320 )
2316 2321 coreconfigitem(
2317 2322 b'smtp',
2318 2323 b'password',
2319 2324 default=None,
2320 2325 )
2321 2326 coreconfigitem(
2322 2327 b'smtp',
2323 2328 b'port',
2324 2329 default=dynamicdefault,
2325 2330 )
2326 2331 coreconfigitem(
2327 2332 b'smtp',
2328 2333 b'tls',
2329 2334 default=b'none',
2330 2335 )
2331 2336 coreconfigitem(
2332 2337 b'smtp',
2333 2338 b'username',
2334 2339 default=None,
2335 2340 )
2336 2341 coreconfigitem(
2337 2342 b'sparse',
2338 2343 b'missingwarning',
2339 2344 default=True,
2340 2345 experimental=True,
2341 2346 )
2342 2347 coreconfigitem(
2343 2348 b'subrepos',
2344 2349 b'allowed',
2345 2350 default=dynamicdefault, # to make backporting simpler
2346 2351 )
2347 2352 coreconfigitem(
2348 2353 b'subrepos',
2349 2354 b'hg:allowed',
2350 2355 default=dynamicdefault,
2351 2356 )
2352 2357 coreconfigitem(
2353 2358 b'subrepos',
2354 2359 b'git:allowed',
2355 2360 default=dynamicdefault,
2356 2361 )
2357 2362 coreconfigitem(
2358 2363 b'subrepos',
2359 2364 b'svn:allowed',
2360 2365 default=dynamicdefault,
2361 2366 )
2362 2367 coreconfigitem(
2363 2368 b'templates',
2364 2369 b'.*',
2365 2370 default=None,
2366 2371 generic=True,
2367 2372 )
2368 2373 coreconfigitem(
2369 2374 b'templateconfig',
2370 2375 b'.*',
2371 2376 default=dynamicdefault,
2372 2377 generic=True,
2373 2378 )
2374 2379 coreconfigitem(
2375 2380 b'trusted',
2376 2381 b'groups',
2377 2382 default=list,
2378 2383 )
2379 2384 coreconfigitem(
2380 2385 b'trusted',
2381 2386 b'users',
2382 2387 default=list,
2383 2388 )
2384 2389 coreconfigitem(
2385 2390 b'ui',
2386 2391 b'_usedassubrepo',
2387 2392 default=False,
2388 2393 )
2389 2394 coreconfigitem(
2390 2395 b'ui',
2391 2396 b'allowemptycommit',
2392 2397 default=False,
2393 2398 )
2394 2399 coreconfigitem(
2395 2400 b'ui',
2396 2401 b'archivemeta',
2397 2402 default=True,
2398 2403 )
2399 2404 coreconfigitem(
2400 2405 b'ui',
2401 2406 b'askusername',
2402 2407 default=False,
2403 2408 )
2404 2409 coreconfigitem(
2405 2410 b'ui',
2406 2411 b'available-memory',
2407 2412 default=None,
2408 2413 )
2409 2414
2410 2415 coreconfigitem(
2411 2416 b'ui',
2412 2417 b'clonebundlefallback',
2413 2418 default=False,
2414 2419 )
2415 2420 coreconfigitem(
2416 2421 b'ui',
2417 2422 b'clonebundleprefers',
2418 2423 default=list,
2419 2424 )
2420 2425 coreconfigitem(
2421 2426 b'ui',
2422 2427 b'clonebundles',
2423 2428 default=True,
2424 2429 )
2425 2430 coreconfigitem(
2426 2431 b'ui',
2427 2432 b'color',
2428 2433 default=b'auto',
2429 2434 )
2430 2435 coreconfigitem(
2431 2436 b'ui',
2432 2437 b'commitsubrepos',
2433 2438 default=False,
2434 2439 )
2435 2440 coreconfigitem(
2436 2441 b'ui',
2437 2442 b'debug',
2438 2443 default=False,
2439 2444 )
2440 2445 coreconfigitem(
2441 2446 b'ui',
2442 2447 b'debugger',
2443 2448 default=None,
2444 2449 )
2445 2450 coreconfigitem(
2446 2451 b'ui',
2447 2452 b'editor',
2448 2453 default=dynamicdefault,
2449 2454 )
2450 2455 coreconfigitem(
2451 2456 b'ui',
2452 2457 b'detailed-exit-code',
2453 2458 default=False,
2454 2459 experimental=True,
2455 2460 )
2456 2461 coreconfigitem(
2457 2462 b'ui',
2458 2463 b'fallbackencoding',
2459 2464 default=None,
2460 2465 )
2461 2466 coreconfigitem(
2462 2467 b'ui',
2463 2468 b'forcecwd',
2464 2469 default=None,
2465 2470 )
2466 2471 coreconfigitem(
2467 2472 b'ui',
2468 2473 b'forcemerge',
2469 2474 default=None,
2470 2475 )
2471 2476 coreconfigitem(
2472 2477 b'ui',
2473 2478 b'formatdebug',
2474 2479 default=False,
2475 2480 )
2476 2481 coreconfigitem(
2477 2482 b'ui',
2478 2483 b'formatjson',
2479 2484 default=False,
2480 2485 )
2481 2486 coreconfigitem(
2482 2487 b'ui',
2483 2488 b'formatted',
2484 2489 default=None,
2485 2490 )
2486 2491 coreconfigitem(
2487 2492 b'ui',
2488 2493 b'interactive',
2489 2494 default=None,
2490 2495 )
2491 2496 coreconfigitem(
2492 2497 b'ui',
2493 2498 b'interface',
2494 2499 default=None,
2495 2500 )
2496 2501 coreconfigitem(
2497 2502 b'ui',
2498 2503 b'interface.chunkselector',
2499 2504 default=None,
2500 2505 )
2501 2506 coreconfigitem(
2502 2507 b'ui',
2503 2508 b'large-file-limit',
2504 2509 default=10 * (2 ** 20),
2505 2510 )
2506 2511 coreconfigitem(
2507 2512 b'ui',
2508 2513 b'logblockedtimes',
2509 2514 default=False,
2510 2515 )
2511 2516 coreconfigitem(
2512 2517 b'ui',
2513 2518 b'merge',
2514 2519 default=None,
2515 2520 )
2516 2521 coreconfigitem(
2517 2522 b'ui',
2518 2523 b'mergemarkers',
2519 2524 default=b'basic',
2520 2525 )
2521 2526 coreconfigitem(
2522 2527 b'ui',
2523 2528 b'message-output',
2524 2529 default=b'stdio',
2525 2530 )
2526 2531 coreconfigitem(
2527 2532 b'ui',
2528 2533 b'nontty',
2529 2534 default=False,
2530 2535 )
2531 2536 coreconfigitem(
2532 2537 b'ui',
2533 2538 b'origbackuppath',
2534 2539 default=None,
2535 2540 )
2536 2541 coreconfigitem(
2537 2542 b'ui',
2538 2543 b'paginate',
2539 2544 default=True,
2540 2545 )
2541 2546 coreconfigitem(
2542 2547 b'ui',
2543 2548 b'patch',
2544 2549 default=None,
2545 2550 )
2546 2551 coreconfigitem(
2547 2552 b'ui',
2548 2553 b'portablefilenames',
2549 2554 default=b'warn',
2550 2555 )
2551 2556 coreconfigitem(
2552 2557 b'ui',
2553 2558 b'promptecho',
2554 2559 default=False,
2555 2560 )
2556 2561 coreconfigitem(
2557 2562 b'ui',
2558 2563 b'quiet',
2559 2564 default=False,
2560 2565 )
2561 2566 coreconfigitem(
2562 2567 b'ui',
2563 2568 b'quietbookmarkmove',
2564 2569 default=False,
2565 2570 )
2566 2571 coreconfigitem(
2567 2572 b'ui',
2568 2573 b'relative-paths',
2569 2574 default=b'legacy',
2570 2575 )
2571 2576 coreconfigitem(
2572 2577 b'ui',
2573 2578 b'remotecmd',
2574 2579 default=b'hg',
2575 2580 )
2576 2581 coreconfigitem(
2577 2582 b'ui',
2578 2583 b'report_untrusted',
2579 2584 default=True,
2580 2585 )
2581 2586 coreconfigitem(
2582 2587 b'ui',
2583 2588 b'rollback',
2584 2589 default=True,
2585 2590 )
2586 2591 coreconfigitem(
2587 2592 b'ui',
2588 2593 b'signal-safe-lock',
2589 2594 default=True,
2590 2595 )
2591 2596 coreconfigitem(
2592 2597 b'ui',
2593 2598 b'slash',
2594 2599 default=False,
2595 2600 )
2596 2601 coreconfigitem(
2597 2602 b'ui',
2598 2603 b'ssh',
2599 2604 default=b'ssh',
2600 2605 )
2601 2606 coreconfigitem(
2602 2607 b'ui',
2603 2608 b'ssherrorhint',
2604 2609 default=None,
2605 2610 )
2606 2611 coreconfigitem(
2607 2612 b'ui',
2608 2613 b'statuscopies',
2609 2614 default=False,
2610 2615 )
2611 2616 coreconfigitem(
2612 2617 b'ui',
2613 2618 b'strict',
2614 2619 default=False,
2615 2620 )
2616 2621 coreconfigitem(
2617 2622 b'ui',
2618 2623 b'style',
2619 2624 default=b'',
2620 2625 )
2621 2626 coreconfigitem(
2622 2627 b'ui',
2623 2628 b'supportcontact',
2624 2629 default=None,
2625 2630 )
2626 2631 coreconfigitem(
2627 2632 b'ui',
2628 2633 b'textwidth',
2629 2634 default=78,
2630 2635 )
2631 2636 coreconfigitem(
2632 2637 b'ui',
2633 2638 b'timeout',
2634 2639 default=b'600',
2635 2640 )
2636 2641 coreconfigitem(
2637 2642 b'ui',
2638 2643 b'timeout.warn',
2639 2644 default=0,
2640 2645 )
2641 2646 coreconfigitem(
2642 2647 b'ui',
2643 2648 b'timestamp-output',
2644 2649 default=False,
2645 2650 )
2646 2651 coreconfigitem(
2647 2652 b'ui',
2648 2653 b'traceback',
2649 2654 default=False,
2650 2655 )
2651 2656 coreconfigitem(
2652 2657 b'ui',
2653 2658 b'tweakdefaults',
2654 2659 default=False,
2655 2660 )
2656 2661 coreconfigitem(b'ui', b'username', alias=[(b'ui', b'user')])
2657 2662 coreconfigitem(
2658 2663 b'ui',
2659 2664 b'verbose',
2660 2665 default=False,
2661 2666 )
2662 2667 coreconfigitem(
2663 2668 b'verify',
2664 2669 b'skipflags',
2665 2670 default=0,
2666 2671 )
2667 2672 coreconfigitem(
2668 2673 b'web',
2669 2674 b'allowbz2',
2670 2675 default=False,
2671 2676 )
2672 2677 coreconfigitem(
2673 2678 b'web',
2674 2679 b'allowgz',
2675 2680 default=False,
2676 2681 )
2677 2682 coreconfigitem(
2678 2683 b'web',
2679 2684 b'allow-pull',
2680 2685 alias=[(b'web', b'allowpull')],
2681 2686 default=True,
2682 2687 )
2683 2688 coreconfigitem(
2684 2689 b'web',
2685 2690 b'allow-push',
2686 2691 alias=[(b'web', b'allow_push')],
2687 2692 default=list,
2688 2693 )
2689 2694 coreconfigitem(
2690 2695 b'web',
2691 2696 b'allowzip',
2692 2697 default=False,
2693 2698 )
2694 2699 coreconfigitem(
2695 2700 b'web',
2696 2701 b'archivesubrepos',
2697 2702 default=False,
2698 2703 )
2699 2704 coreconfigitem(
2700 2705 b'web',
2701 2706 b'cache',
2702 2707 default=True,
2703 2708 )
2704 2709 coreconfigitem(
2705 2710 b'web',
2706 2711 b'comparisoncontext',
2707 2712 default=5,
2708 2713 )
2709 2714 coreconfigitem(
2710 2715 b'web',
2711 2716 b'contact',
2712 2717 default=None,
2713 2718 )
2714 2719 coreconfigitem(
2715 2720 b'web',
2716 2721 b'deny_push',
2717 2722 default=list,
2718 2723 )
2719 2724 coreconfigitem(
2720 2725 b'web',
2721 2726 b'guessmime',
2722 2727 default=False,
2723 2728 )
2724 2729 coreconfigitem(
2725 2730 b'web',
2726 2731 b'hidden',
2727 2732 default=False,
2728 2733 )
2729 2734 coreconfigitem(
2730 2735 b'web',
2731 2736 b'labels',
2732 2737 default=list,
2733 2738 )
2734 2739 coreconfigitem(
2735 2740 b'web',
2736 2741 b'logoimg',
2737 2742 default=b'hglogo.png',
2738 2743 )
2739 2744 coreconfigitem(
2740 2745 b'web',
2741 2746 b'logourl',
2742 2747 default=b'https://mercurial-scm.org/',
2743 2748 )
2744 2749 coreconfigitem(
2745 2750 b'web',
2746 2751 b'accesslog',
2747 2752 default=b'-',
2748 2753 )
2749 2754 coreconfigitem(
2750 2755 b'web',
2751 2756 b'address',
2752 2757 default=b'',
2753 2758 )
2754 2759 coreconfigitem(
2755 2760 b'web',
2756 2761 b'allow-archive',
2757 2762 alias=[(b'web', b'allow_archive')],
2758 2763 default=list,
2759 2764 )
2760 2765 coreconfigitem(
2761 2766 b'web',
2762 2767 b'allow_read',
2763 2768 default=list,
2764 2769 )
2765 2770 coreconfigitem(
2766 2771 b'web',
2767 2772 b'baseurl',
2768 2773 default=None,
2769 2774 )
2770 2775 coreconfigitem(
2771 2776 b'web',
2772 2777 b'cacerts',
2773 2778 default=None,
2774 2779 )
2775 2780 coreconfigitem(
2776 2781 b'web',
2777 2782 b'certificate',
2778 2783 default=None,
2779 2784 )
2780 2785 coreconfigitem(
2781 2786 b'web',
2782 2787 b'collapse',
2783 2788 default=False,
2784 2789 )
2785 2790 coreconfigitem(
2786 2791 b'web',
2787 2792 b'csp',
2788 2793 default=None,
2789 2794 )
2790 2795 coreconfigitem(
2791 2796 b'web',
2792 2797 b'deny_read',
2793 2798 default=list,
2794 2799 )
2795 2800 coreconfigitem(
2796 2801 b'web',
2797 2802 b'descend',
2798 2803 default=True,
2799 2804 )
2800 2805 coreconfigitem(
2801 2806 b'web',
2802 2807 b'description',
2803 2808 default=b"",
2804 2809 )
2805 2810 coreconfigitem(
2806 2811 b'web',
2807 2812 b'encoding',
2808 2813 default=lambda: encoding.encoding,
2809 2814 )
2810 2815 coreconfigitem(
2811 2816 b'web',
2812 2817 b'errorlog',
2813 2818 default=b'-',
2814 2819 )
2815 2820 coreconfigitem(
2816 2821 b'web',
2817 2822 b'ipv6',
2818 2823 default=False,
2819 2824 )
2820 2825 coreconfigitem(
2821 2826 b'web',
2822 2827 b'maxchanges',
2823 2828 default=10,
2824 2829 )
2825 2830 coreconfigitem(
2826 2831 b'web',
2827 2832 b'maxfiles',
2828 2833 default=10,
2829 2834 )
2830 2835 coreconfigitem(
2831 2836 b'web',
2832 2837 b'maxshortchanges',
2833 2838 default=60,
2834 2839 )
2835 2840 coreconfigitem(
2836 2841 b'web',
2837 2842 b'motd',
2838 2843 default=b'',
2839 2844 )
2840 2845 coreconfigitem(
2841 2846 b'web',
2842 2847 b'name',
2843 2848 default=dynamicdefault,
2844 2849 )
2845 2850 coreconfigitem(
2846 2851 b'web',
2847 2852 b'port',
2848 2853 default=8000,
2849 2854 )
2850 2855 coreconfigitem(
2851 2856 b'web',
2852 2857 b'prefix',
2853 2858 default=b'',
2854 2859 )
2855 2860 coreconfigitem(
2856 2861 b'web',
2857 2862 b'push_ssl',
2858 2863 default=True,
2859 2864 )
2860 2865 coreconfigitem(
2861 2866 b'web',
2862 2867 b'refreshinterval',
2863 2868 default=20,
2864 2869 )
2865 2870 coreconfigitem(
2866 2871 b'web',
2867 2872 b'server-header',
2868 2873 default=None,
2869 2874 )
2870 2875 coreconfigitem(
2871 2876 b'web',
2872 2877 b'static',
2873 2878 default=None,
2874 2879 )
2875 2880 coreconfigitem(
2876 2881 b'web',
2877 2882 b'staticurl',
2878 2883 default=None,
2879 2884 )
2880 2885 coreconfigitem(
2881 2886 b'web',
2882 2887 b'stripes',
2883 2888 default=1,
2884 2889 )
2885 2890 coreconfigitem(
2886 2891 b'web',
2887 2892 b'style',
2888 2893 default=b'paper',
2889 2894 )
2890 2895 coreconfigitem(
2891 2896 b'web',
2892 2897 b'templates',
2893 2898 default=None,
2894 2899 )
2895 2900 coreconfigitem(
2896 2901 b'web',
2897 2902 b'view',
2898 2903 default=b'served',
2899 2904 experimental=True,
2900 2905 )
2901 2906 coreconfigitem(
2902 2907 b'worker',
2903 2908 b'backgroundclose',
2904 2909 default=dynamicdefault,
2905 2910 )
2906 2911 # Windows defaults to a limit of 512 open files. A buffer of 128
2907 2912 # should give us enough headway.
2908 2913 coreconfigitem(
2909 2914 b'worker',
2910 2915 b'backgroundclosemaxqueue',
2911 2916 default=384,
2912 2917 )
2913 2918 coreconfigitem(
2914 2919 b'worker',
2915 2920 b'backgroundcloseminfilecount',
2916 2921 default=2048,
2917 2922 )
2918 2923 coreconfigitem(
2919 2924 b'worker',
2920 2925 b'backgroundclosethreadcount',
2921 2926 default=4,
2922 2927 )
2923 2928 coreconfigitem(
2924 2929 b'worker',
2925 2930 b'enabled',
2926 2931 default=True,
2927 2932 )
2928 2933 coreconfigitem(
2929 2934 b'worker',
2930 2935 b'numcpus',
2931 2936 default=None,
2932 2937 )
2933 2938
2934 2939 # Rebase related configuration moved to core because other extension are doing
2935 2940 # strange things. For example, shelve import the extensions to reuse some bit
2936 2941 # without formally loading it.
2937 2942 coreconfigitem(
2938 2943 b'commands',
2939 2944 b'rebase.requiredest',
2940 2945 default=False,
2941 2946 )
2942 2947 coreconfigitem(
2943 2948 b'experimental',
2944 2949 b'rebaseskipobsolete',
2945 2950 default=True,
2946 2951 )
2947 2952 coreconfigitem(
2948 2953 b'rebase',
2949 2954 b'singletransaction',
2950 2955 default=False,
2951 2956 )
2952 2957 coreconfigitem(
2953 2958 b'rebase',
2954 2959 b'experimental.inmemory',
2955 2960 default=False,
2956 2961 )
2957 2962
2958 2963 # This setting controls creation of a rebase_source extra field
2959 2964 # during rebase. When False, no such field is created. This is
2960 2965 # useful eg for incrementally converting changesets and then
2961 2966 # rebasing them onto an existing repo.
2962 2967 # WARNING: this is an advanced setting reserved for people who know
2963 2968 # exactly what they are doing. Misuse of this setting can easily
2964 2969 # result in obsmarker cycles and a vivid headache.
2965 2970 coreconfigitem(
2966 2971 b'rebase',
2967 2972 b'store-source',
2968 2973 default=True,
2969 2974 experimental=True,
2970 2975 )
@@ -1,287 +1,314 b''
1 1 # hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005, 2006 Olivia Mackall <olivia@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
10 10 import base64
11 11 import errno
12 12 import mimetypes
13 13 import os
14 14 import stat
15 15
16 from ..i18n import _
16 17 from ..pycompat import (
17 18 getattr,
18 19 open,
19 20 )
20 21 from .. import (
21 22 encoding,
22 23 pycompat,
23 24 templater,
24 25 util,
25 26 )
26 27
27 28 httpserver = util.httpserver
28 29
29 30 HTTP_OK = 200
30 31 HTTP_CREATED = 201
31 32 HTTP_NOT_MODIFIED = 304
32 33 HTTP_BAD_REQUEST = 400
33 34 HTTP_UNAUTHORIZED = 401
34 35 HTTP_FORBIDDEN = 403
35 36 HTTP_NOT_FOUND = 404
36 37 HTTP_METHOD_NOT_ALLOWED = 405
37 38 HTTP_NOT_ACCEPTABLE = 406
38 39 HTTP_UNSUPPORTED_MEDIA_TYPE = 415
39 40 HTTP_SERVER_ERROR = 500
40 41
41 42
42 43 def ismember(ui, username, userlist):
43 44 """Check if username is a member of userlist.
44 45
45 46 If userlist has a single '*' member, all users are considered members.
46 47 Can be overridden by extensions to provide more complex authorization
47 48 schemes.
48 49 """
49 50 return userlist == [b'*'] or username in userlist
50 51
51 52
53 def hashiddenaccess(repo, req):
54 if bool(req.qsparams.get(b'access-hidden')):
55 # Disable this by default for now. Main risk is to get critical
56 # information exposed through this. This is expecially risky if
57 # someone decided to make a changeset secret for good reason, but
58 # its predecessors are still draft.
59 #
60 # The feature is currently experimental, so we can still decide to
61 # change the default.
62 ui = repo.ui
63 allow = ui.configlist(b'experimental', b'server.allow-hidden-access')
64 user = req.remoteuser
65 if allow and ismember(ui, user, allow):
66 return True
67 else:
68 msg = (
69 _(
70 b'ignoring request to access hidden changeset by '
71 b'unauthorized user: %r\n'
72 )
73 % user
74 )
75 ui.warn(msg)
76 return False
77
78
52 79 def checkauthz(hgweb, req, op):
53 80 """Check permission for operation based on request data (including
54 81 authentication info). Return if op allowed, else raise an ErrorResponse
55 82 exception."""
56 83
57 84 user = req.remoteuser
58 85
59 86 deny_read = hgweb.configlist(b'web', b'deny_read')
60 87 if deny_read and (not user or ismember(hgweb.repo.ui, user, deny_read)):
61 88 raise ErrorResponse(HTTP_UNAUTHORIZED, b'read not authorized')
62 89
63 90 allow_read = hgweb.configlist(b'web', b'allow_read')
64 91 if allow_read and (not ismember(hgweb.repo.ui, user, allow_read)):
65 92 raise ErrorResponse(HTTP_UNAUTHORIZED, b'read not authorized')
66 93
67 94 if op == b'pull' and not hgweb.allowpull:
68 95 raise ErrorResponse(HTTP_UNAUTHORIZED, b'pull not authorized')
69 96 elif op == b'pull' or op is None: # op is None for interface requests
70 97 return
71 98
72 99 # Allow LFS uploading via PUT requests
73 100 if op == b'upload':
74 101 if req.method != b'PUT':
75 102 msg = b'upload requires PUT request'
76 103 raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
77 104 # enforce that you can only push using POST requests
78 105 elif req.method != b'POST':
79 106 msg = b'push requires POST request'
80 107 raise ErrorResponse(HTTP_METHOD_NOT_ALLOWED, msg)
81 108
82 109 # require ssl by default for pushing, auth info cannot be sniffed
83 110 # and replayed
84 111 if hgweb.configbool(b'web', b'push_ssl') and req.urlscheme != b'https':
85 112 raise ErrorResponse(HTTP_FORBIDDEN, b'ssl required')
86 113
87 114 deny = hgweb.configlist(b'web', b'deny_push')
88 115 if deny and (not user or ismember(hgweb.repo.ui, user, deny)):
89 116 raise ErrorResponse(HTTP_UNAUTHORIZED, b'push not authorized')
90 117
91 118 allow = hgweb.configlist(b'web', b'allow-push')
92 119 if not (allow and ismember(hgweb.repo.ui, user, allow)):
93 120 raise ErrorResponse(HTTP_UNAUTHORIZED, b'push not authorized')
94 121
95 122
96 123 # Hooks for hgweb permission checks; extensions can add hooks here.
97 124 # Each hook is invoked like this: hook(hgweb, request, operation),
98 125 # where operation is either read, pull, push or upload. Hooks should either
99 126 # raise an ErrorResponse exception, or just return.
100 127 #
101 128 # It is possible to do both authentication and authorization through
102 129 # this.
103 130 permhooks = [checkauthz]
104 131
105 132
106 133 class ErrorResponse(Exception):
107 134 def __init__(self, code, message=None, headers=None):
108 135 if message is None:
109 136 message = _statusmessage(code)
110 137 Exception.__init__(self, pycompat.sysstr(message))
111 138 self.code = code
112 139 if headers is None:
113 140 headers = []
114 141 self.headers = headers
115 142 self.message = message
116 143
117 144
118 145 class continuereader:
119 146 """File object wrapper to handle HTTP 100-continue.
120 147
121 148 This is used by servers so they automatically handle Expect: 100-continue
122 149 request headers. On first read of the request body, the 100 Continue
123 150 response is sent. This should trigger the client into actually sending
124 151 the request body.
125 152 """
126 153
127 154 def __init__(self, f, write):
128 155 self.f = f
129 156 self._write = write
130 157 self.continued = False
131 158
132 159 def read(self, amt=-1):
133 160 if not self.continued:
134 161 self.continued = True
135 162 self._write(b'HTTP/1.1 100 Continue\r\n\r\n')
136 163 return self.f.read(amt)
137 164
138 165 def __getattr__(self, attr):
139 166 if attr in (b'close', b'readline', b'readlines', b'__iter__'):
140 167 return getattr(self.f, attr)
141 168 raise AttributeError
142 169
143 170
144 171 def _statusmessage(code):
145 172 responses = httpserver.basehttprequesthandler.responses
146 173 return pycompat.bytesurl(responses.get(code, ('Error', 'Unknown error'))[0])
147 174
148 175
149 176 def statusmessage(code, message=None):
150 177 return b'%d %s' % (code, message or _statusmessage(code))
151 178
152 179
153 180 def get_stat(spath, fn):
154 181 """stat fn if it exists, spath otherwise"""
155 182 cl_path = os.path.join(spath, fn)
156 183 if os.path.exists(cl_path):
157 184 return os.stat(cl_path)
158 185 else:
159 186 return os.stat(spath)
160 187
161 188
162 189 def get_mtime(spath):
163 190 return get_stat(spath, b"00changelog.i")[stat.ST_MTIME]
164 191
165 192
166 193 def ispathsafe(path):
167 194 """Determine if a path is safe to use for filesystem access."""
168 195 parts = path.split(b'/')
169 196 for part in parts:
170 197 if (
171 198 part in (b'', pycompat.oscurdir, pycompat.ospardir)
172 199 or pycompat.ossep in part
173 200 or pycompat.osaltsep is not None
174 201 and pycompat.osaltsep in part
175 202 ):
176 203 return False
177 204
178 205 return True
179 206
180 207
181 208 def staticfile(templatepath, directory, fname, res):
182 209 """return a file inside directory with guessed Content-Type header
183 210
184 211 fname always uses '/' as directory separator and isn't allowed to
185 212 contain unusual path components.
186 213 Content-Type is guessed using the mimetypes module.
187 214 Return an empty string if fname is illegal or file not found.
188 215
189 216 """
190 217 if not ispathsafe(fname):
191 218 return
192 219
193 220 if not directory:
194 221 tp = templatepath or templater.templatedir()
195 222 if tp is not None:
196 223 directory = os.path.join(tp, b'static')
197 224
198 225 fpath = os.path.join(*fname.split(b'/'))
199 226 ct = pycompat.sysbytes(
200 227 mimetypes.guess_type(pycompat.fsdecode(fpath))[0] or r"text/plain"
201 228 )
202 229 path = os.path.join(directory, fpath)
203 230 try:
204 231 os.stat(path)
205 232 with open(path, b'rb') as fh:
206 233 data = fh.read()
207 234 except TypeError:
208 235 raise ErrorResponse(HTTP_SERVER_ERROR, b'illegal filename')
209 236 except OSError as err:
210 237 if err.errno == errno.ENOENT:
211 238 raise ErrorResponse(HTTP_NOT_FOUND)
212 239 else:
213 240 raise ErrorResponse(
214 241 HTTP_SERVER_ERROR, encoding.strtolocal(err.strerror)
215 242 )
216 243
217 244 res.headers[b'Content-Type'] = ct
218 245 res.setbodybytes(data)
219 246 return res
220 247
221 248
222 249 def paritygen(stripecount, offset=0):
223 250 """count parity of horizontal stripes for easier reading"""
224 251 if stripecount and offset:
225 252 # account for offset, e.g. due to building the list in reverse
226 253 count = (stripecount + offset) % stripecount
227 254 parity = (stripecount + offset) // stripecount & 1
228 255 else:
229 256 count = 0
230 257 parity = 0
231 258 while True:
232 259 yield parity
233 260 count += 1
234 261 if stripecount and count >= stripecount:
235 262 parity = 1 - parity
236 263 count = 0
237 264
238 265
239 266 def get_contact(config):
240 267 """Return repo contact information or empty string.
241 268
242 269 web.contact is the primary source, but if that is not set, try
243 270 ui.username or $EMAIL as a fallback to display something useful.
244 271 """
245 272 return (
246 273 config(b"web", b"contact")
247 274 or config(b"ui", b"username")
248 275 or encoding.environ.get(b"EMAIL")
249 276 or b""
250 277 )
251 278
252 279
253 280 def cspvalues(ui):
254 281 """Obtain the Content-Security-Policy header and nonce value.
255 282
256 283 Returns a 2-tuple of the CSP header value and the nonce value.
257 284
258 285 First value is ``None`` if CSP isn't enabled. Second value is ``None``
259 286 if CSP isn't enabled or if the CSP header doesn't need a nonce.
260 287 """
261 288 # Without demandimport, "import uuid" could have an immediate side-effect
262 289 # running "ldconfig" on Linux trying to find libuuid.
263 290 # With Python <= 2.7.12, that "ldconfig" is run via a shell and the shell
264 291 # may pollute the terminal with:
265 292 #
266 293 # shell-init: error retrieving current directory: getcwd: cannot access
267 294 # parent directories: No such file or directory
268 295 #
269 296 # Python >= 2.7.13 has fixed it by running "ldconfig" directly without a
270 297 # shell (hg changeset a09ae70f3489).
271 298 #
272 299 # Moved "import uuid" from here so it's executed after we know we have
273 300 # a sane cwd (i.e. after dispatch.py cwd check).
274 301 #
275 302 # We can move it back once we no longer need Python <= 2.7.12 support.
276 303 import uuid
277 304
278 305 # Don't allow untrusted CSP setting since it be disable protections
279 306 # from a trusted/global source.
280 307 csp = ui.config(b'web', b'csp', untrusted=False)
281 308 nonce = None
282 309
283 310 if csp and b'%nonce%' in csp:
284 311 nonce = base64.urlsafe_b64encode(uuid.uuid4().bytes).rstrip(b'=')
285 312 csp = csp.replace(b'%nonce%', nonce)
286 313
287 314 return csp, nonce
@@ -1,516 +1,527 b''
1 1 # hgweb/hgweb_mod.py - Web interface for a repository.
2 2 #
3 3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 4 # Copyright 2005-2007 Olivia Mackall <olivia@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
10 10 import contextlib
11 11 import os
12 12
13 13 from .common import (
14 14 ErrorResponse,
15 15 HTTP_BAD_REQUEST,
16 16 cspvalues,
17 17 permhooks,
18 18 statusmessage,
19 19 )
20 20 from ..pycompat import getattr
21 21
22 22 from .. import (
23 23 encoding,
24 24 error,
25 25 extensions,
26 26 formatter,
27 27 hg,
28 28 hook,
29 29 profiling,
30 30 pycompat,
31 31 registrar,
32 32 repoview,
33 33 templatefilters,
34 34 templater,
35 35 templateutil,
36 36 ui as uimod,
37 37 util,
38 38 wireprotoserver,
39 39 )
40 40
41 41 from . import (
42 common,
42 43 request as requestmod,
43 44 webcommands,
44 45 webutil,
45 46 wsgicgi,
46 47 )
47 48
48 49
49 50 def getstyle(req, configfn, templatepath):
50 51 styles = (
51 52 req.qsparams.get(b'style', None),
52 53 configfn(b'web', b'style'),
53 54 b'paper',
54 55 )
55 56 return styles, _stylemap(styles, templatepath)
56 57
57 58
58 59 def _stylemap(styles, path=None):
59 60 """Return path to mapfile for a given style.
60 61
61 62 Searches mapfile in the following locations:
62 63 1. templatepath/style/map
63 64 2. templatepath/map-style
64 65 3. templatepath/map
65 66 """
66 67
67 68 for style in styles:
68 69 # only plain name is allowed to honor template paths
69 70 if (
70 71 not style
71 72 or style in (pycompat.oscurdir, pycompat.ospardir)
72 73 or pycompat.ossep in style
73 74 or pycompat.osaltsep
74 75 and pycompat.osaltsep in style
75 76 ):
76 77 continue
77 78 locations = (os.path.join(style, b'map'), b'map-' + style, b'map')
78 79
79 80 for location in locations:
80 81 mapfile, fp = templater.try_open_template(location, path)
81 82 if mapfile:
82 83 return style, mapfile, fp
83 84
84 85 raise RuntimeError(b"No hgweb templates found in %r" % path)
85 86
86 87
87 88 def makebreadcrumb(url, prefix=b''):
88 89 """Return a 'URL breadcrumb' list
89 90
90 91 A 'URL breadcrumb' is a list of URL-name pairs,
91 92 corresponding to each of the path items on a URL.
92 93 This can be used to create path navigation entries.
93 94 """
94 95 if url.endswith(b'/'):
95 96 url = url[:-1]
96 97 if prefix:
97 98 url = b'/' + prefix + url
98 99 relpath = url
99 100 if relpath.startswith(b'/'):
100 101 relpath = relpath[1:]
101 102
102 103 breadcrumb = []
103 104 urlel = url
104 105 pathitems = [b''] + relpath.split(b'/')
105 106 for pathel in reversed(pathitems):
106 107 if not pathel or not urlel:
107 108 break
108 109 breadcrumb.append({b'url': urlel, b'name': pathel})
109 110 urlel = os.path.dirname(urlel)
110 111 return templateutil.mappinglist(reversed(breadcrumb))
111 112
112 113
113 114 class requestcontext:
114 115 """Holds state/context for an individual request.
115 116
116 117 Servers can be multi-threaded. Holding state on the WSGI application
117 118 is prone to race conditions. Instances of this class exist to hold
118 119 mutable and race-free state for requests.
119 120 """
120 121
121 122 def __init__(self, app, repo, req, res):
122 123 self.repo = repo
123 124 self.reponame = app.reponame
124 125 self.req = req
125 126 self.res = res
126 127
128 # Only works if the filter actually support being upgraded to show
129 # visible changesets
130 current_filter = repo.filtername
131 if (
132 common.hashiddenaccess(repo, req)
133 and current_filter is not None
134 and current_filter + b'.hidden' in repoview.filtertable
135 ):
136 self.repo = self.repo.filtered(repo.filtername + b'.hidden')
137
127 138 self.maxchanges = self.configint(b'web', b'maxchanges')
128 139 self.stripecount = self.configint(b'web', b'stripes')
129 140 self.maxshortchanges = self.configint(b'web', b'maxshortchanges')
130 141 self.maxfiles = self.configint(b'web', b'maxfiles')
131 142 self.allowpull = self.configbool(b'web', b'allow-pull')
132 143
133 144 # we use untrusted=False to prevent a repo owner from using
134 145 # web.templates in .hg/hgrc to get access to any file readable
135 146 # by the user running the CGI script
136 147 self.templatepath = self.config(b'web', b'templates', untrusted=False)
137 148
138 149 # This object is more expensive to build than simple config values.
139 150 # It is shared across requests. The app will replace the object
140 151 # if it is updated. Since this is a reference and nothing should
141 152 # modify the underlying object, it should be constant for the lifetime
142 153 # of the request.
143 154 self.websubtable = app.websubtable
144 155
145 156 self.csp, self.nonce = cspvalues(self.repo.ui)
146 157
147 158 # Trust the settings from the .hg/hgrc files by default.
148 159 def config(self, *args, **kwargs):
149 160 kwargs.setdefault('untrusted', True)
150 161 return self.repo.ui.config(*args, **kwargs)
151 162
152 163 def configbool(self, *args, **kwargs):
153 164 kwargs.setdefault('untrusted', True)
154 165 return self.repo.ui.configbool(*args, **kwargs)
155 166
156 167 def configint(self, *args, **kwargs):
157 168 kwargs.setdefault('untrusted', True)
158 169 return self.repo.ui.configint(*args, **kwargs)
159 170
160 171 def configlist(self, *args, **kwargs):
161 172 kwargs.setdefault('untrusted', True)
162 173 return self.repo.ui.configlist(*args, **kwargs)
163 174
164 175 def archivelist(self, nodeid):
165 176 return webutil.archivelist(self.repo.ui, nodeid)
166 177
167 178 def templater(self, req):
168 179 # determine scheme, port and server name
169 180 # this is needed to create absolute urls
170 181 logourl = self.config(b'web', b'logourl')
171 182 logoimg = self.config(b'web', b'logoimg')
172 183 staticurl = (
173 184 self.config(b'web', b'staticurl')
174 185 or req.apppath.rstrip(b'/') + b'/static/'
175 186 )
176 187 if not staticurl.endswith(b'/'):
177 188 staticurl += b'/'
178 189
179 190 # figure out which style to use
180 191
181 192 vars = {}
182 193 styles, (style, mapfile, fp) = getstyle(
183 194 req, self.config, self.templatepath
184 195 )
185 196 if style == styles[0]:
186 197 vars[b'style'] = style
187 198
188 199 sessionvars = webutil.sessionvars(vars, b'?')
189 200
190 201 if not self.reponame:
191 202 self.reponame = (
192 203 self.config(b'web', b'name', b'')
193 204 or req.reponame
194 205 or req.apppath
195 206 or self.repo.root
196 207 )
197 208
198 209 filters = {}
199 210 templatefilter = registrar.templatefilter(filters)
200 211
201 212 @templatefilter(b'websub', intype=bytes)
202 213 def websubfilter(text):
203 214 return templatefilters.websub(text, self.websubtable)
204 215
205 216 # create the templater
206 217 # TODO: export all keywords: defaults = templatekw.keywords.copy()
207 218 defaults = {
208 219 b'url': req.apppath + b'/',
209 220 b'logourl': logourl,
210 221 b'logoimg': logoimg,
211 222 b'staticurl': staticurl,
212 223 b'urlbase': req.advertisedbaseurl,
213 224 b'repo': self.reponame,
214 225 b'encoding': encoding.encoding,
215 226 b'sessionvars': sessionvars,
216 227 b'pathdef': makebreadcrumb(req.apppath),
217 228 b'style': style,
218 229 b'nonce': self.nonce,
219 230 }
220 231 templatekeyword = registrar.templatekeyword(defaults)
221 232
222 233 @templatekeyword(b'motd', requires=())
223 234 def motd(context, mapping):
224 235 yield self.config(b'web', b'motd')
225 236
226 237 tres = formatter.templateresources(self.repo.ui, self.repo)
227 238 return templater.templater.frommapfile(
228 239 mapfile, fp=fp, filters=filters, defaults=defaults, resources=tres
229 240 )
230 241
231 242 def sendtemplate(self, name, **kwargs):
232 243 """Helper function to send a response generated from a template."""
233 244 if self.req.method != b'HEAD':
234 245 kwargs = pycompat.byteskwargs(kwargs)
235 246 self.res.setbodygen(self.tmpl.generate(name, kwargs))
236 247 return self.res.sendresponse()
237 248
238 249
239 250 class hgweb:
240 251 """HTTP server for individual repositories.
241 252
242 253 Instances of this class serve HTTP responses for a particular
243 254 repository.
244 255
245 256 Instances are typically used as WSGI applications.
246 257
247 258 Some servers are multi-threaded. On these servers, there may
248 259 be multiple active threads inside __call__.
249 260 """
250 261
251 262 def __init__(self, repo, name=None, baseui=None):
252 263 if isinstance(repo, bytes):
253 264 if baseui:
254 265 u = baseui.copy()
255 266 else:
256 267 u = uimod.ui.load()
257 268 extensions.loadall(u)
258 269 extensions.populateui(u)
259 270 r = hg.repository(u, repo)
260 271 else:
261 272 # we trust caller to give us a private copy
262 273 r = repo
263 274
264 275 r.ui.setconfig(b'ui', b'report_untrusted', b'off', b'hgweb')
265 276 r.baseui.setconfig(b'ui', b'report_untrusted', b'off', b'hgweb')
266 277 r.ui.setconfig(b'ui', b'nontty', b'true', b'hgweb')
267 278 r.baseui.setconfig(b'ui', b'nontty', b'true', b'hgweb')
268 279 # resolve file patterns relative to repo root
269 280 r.ui.setconfig(b'ui', b'forcecwd', r.root, b'hgweb')
270 281 r.baseui.setconfig(b'ui', b'forcecwd', r.root, b'hgweb')
271 282 # it's unlikely that we can replace signal handlers in WSGI server,
272 283 # and mod_wsgi issues a big warning. a plain hgweb process (with no
273 284 # threading) could replace signal handlers, but we don't bother
274 285 # conditionally enabling it.
275 286 r.ui.setconfig(b'ui', b'signal-safe-lock', b'false', b'hgweb')
276 287 r.baseui.setconfig(b'ui', b'signal-safe-lock', b'false', b'hgweb')
277 288 # displaying bundling progress bar while serving feel wrong and may
278 289 # break some wsgi implementation.
279 290 r.ui.setconfig(b'progress', b'disable', b'true', b'hgweb')
280 291 r.baseui.setconfig(b'progress', b'disable', b'true', b'hgweb')
281 292 self._repos = [hg.cachedlocalrepo(self._webifyrepo(r))]
282 293 self._lastrepo = self._repos[0]
283 294 hook.redirect(True)
284 295 self.reponame = name
285 296
286 297 def _webifyrepo(self, repo):
287 298 repo = getwebview(repo)
288 299 self.websubtable = webutil.getwebsubs(repo)
289 300 return repo
290 301
291 302 @contextlib.contextmanager
292 303 def _obtainrepo(self):
293 304 """Obtain a repo unique to the caller.
294 305
295 306 Internally we maintain a stack of cachedlocalrepo instances
296 307 to be handed out. If one is available, we pop it and return it,
297 308 ensuring it is up to date in the process. If one is not available,
298 309 we clone the most recently used repo instance and return it.
299 310
300 311 It is currently possible for the stack to grow without bounds
301 312 if the server allows infinite threads. However, servers should
302 313 have a thread limit, thus establishing our limit.
303 314 """
304 315 if self._repos:
305 316 cached = self._repos.pop()
306 317 r, created = cached.fetch()
307 318 else:
308 319 cached = self._lastrepo.copy()
309 320 r, created = cached.fetch()
310 321 if created:
311 322 r = self._webifyrepo(r)
312 323
313 324 self._lastrepo = cached
314 325 self.mtime = cached.mtime
315 326 try:
316 327 yield r
317 328 finally:
318 329 self._repos.append(cached)
319 330
320 331 def run(self):
321 332 """Start a server from CGI environment.
322 333
323 334 Modern servers should be using WSGI and should avoid this
324 335 method, if possible.
325 336 """
326 337 if not encoding.environ.get(b'GATEWAY_INTERFACE', b'').startswith(
327 338 b"CGI/1."
328 339 ):
329 340 raise RuntimeError(
330 341 b"This function is only intended to be "
331 342 b"called while running as a CGI script."
332 343 )
333 344 wsgicgi.launch(self)
334 345
335 346 def __call__(self, env, respond):
336 347 """Run the WSGI application.
337 348
338 349 This may be called by multiple threads.
339 350 """
340 351 req = requestmod.parserequestfromenv(env)
341 352 res = requestmod.wsgiresponse(req, respond)
342 353
343 354 return self.run_wsgi(req, res)
344 355
345 356 def run_wsgi(self, req, res):
346 357 """Internal method to run the WSGI application.
347 358
348 359 This is typically only called by Mercurial. External consumers
349 360 should be using instances of this class as the WSGI application.
350 361 """
351 362 with self._obtainrepo() as repo:
352 363 profile = repo.ui.configbool(b'profiling', b'enabled')
353 364 with profiling.profile(repo.ui, enabled=profile):
354 365 for r in self._runwsgi(req, res, repo):
355 366 yield r
356 367
357 368 def _runwsgi(self, req, res, repo):
358 369 rctx = requestcontext(self, repo, req, res)
359 370
360 371 # This state is global across all threads.
361 372 encoding.encoding = rctx.config(b'web', b'encoding')
362 373 rctx.repo.ui.environ = req.rawenv
363 374
364 375 if rctx.csp:
365 376 # hgwebdir may have added CSP header. Since we generate our own,
366 377 # replace it.
367 378 res.headers[b'Content-Security-Policy'] = rctx.csp
368 379
369 380 handled = wireprotoserver.handlewsgirequest(
370 381 rctx, req, res, self.check_perm
371 382 )
372 383 if handled:
373 384 return res.sendresponse()
374 385
375 386 # Old implementations of hgweb supported dispatching the request via
376 387 # the initial query string parameter instead of using PATH_INFO.
377 388 # If PATH_INFO is present (signaled by ``req.dispatchpath`` having
378 389 # a value), we use it. Otherwise fall back to the query string.
379 390 if req.dispatchpath is not None:
380 391 query = req.dispatchpath
381 392 else:
382 393 query = req.querystring.partition(b'&')[0].partition(b';')[0]
383 394
384 395 # translate user-visible url structure to internal structure
385 396
386 397 args = query.split(b'/', 2)
387 398 if b'cmd' not in req.qsparams and args and args[0]:
388 399 cmd = args.pop(0)
389 400 style = cmd.rfind(b'-')
390 401 if style != -1:
391 402 req.qsparams[b'style'] = cmd[:style]
392 403 cmd = cmd[style + 1 :]
393 404
394 405 # avoid accepting e.g. style parameter as command
395 406 if util.safehasattr(webcommands, cmd):
396 407 req.qsparams[b'cmd'] = cmd
397 408
398 409 if cmd == b'static':
399 410 req.qsparams[b'file'] = b'/'.join(args)
400 411 else:
401 412 if args and args[0]:
402 413 node = args.pop(0).replace(b'%2F', b'/')
403 414 req.qsparams[b'node'] = node
404 415 if args:
405 416 if b'file' in req.qsparams:
406 417 del req.qsparams[b'file']
407 418 for a in args:
408 419 req.qsparams.add(b'file', a)
409 420
410 421 ua = req.headers.get(b'User-Agent', b'')
411 422 if cmd == b'rev' and b'mercurial' in ua:
412 423 req.qsparams[b'style'] = b'raw'
413 424
414 425 if cmd == b'archive':
415 426 fn = req.qsparams[b'node']
416 427 for type_, spec in webutil.archivespecs.items():
417 428 ext = spec[2]
418 429 if fn.endswith(ext):
419 430 req.qsparams[b'node'] = fn[: -len(ext)]
420 431 req.qsparams[b'type'] = type_
421 432 else:
422 433 cmd = req.qsparams.get(b'cmd', b'')
423 434
424 435 # process the web interface request
425 436
426 437 try:
427 438 rctx.tmpl = rctx.templater(req)
428 439 ctype = rctx.tmpl.render(
429 440 b'mimetype', {b'encoding': encoding.encoding}
430 441 )
431 442
432 443 # check read permissions non-static content
433 444 if cmd != b'static':
434 445 self.check_perm(rctx, req, None)
435 446
436 447 if cmd == b'':
437 448 req.qsparams[b'cmd'] = rctx.tmpl.render(b'default', {})
438 449 cmd = req.qsparams[b'cmd']
439 450
440 451 # Don't enable caching if using a CSP nonce because then it wouldn't
441 452 # be a nonce.
442 453 if rctx.configbool(b'web', b'cache') and not rctx.nonce:
443 454 tag = b'W/"%d"' % self.mtime
444 455 if req.headers.get(b'If-None-Match') == tag:
445 456 res.status = b'304 Not Modified'
446 457 # Content-Type may be defined globally. It isn't valid on a
447 458 # 304, so discard it.
448 459 try:
449 460 del res.headers[b'Content-Type']
450 461 except KeyError:
451 462 pass
452 463 # Response body not allowed on 304.
453 464 res.setbodybytes(b'')
454 465 return res.sendresponse()
455 466
456 467 res.headers[b'ETag'] = tag
457 468
458 469 if cmd not in webcommands.__all__:
459 470 msg = b'no such method: %s' % cmd
460 471 raise ErrorResponse(HTTP_BAD_REQUEST, msg)
461 472 else:
462 473 # Set some globals appropriate for web handlers. Commands can
463 474 # override easily enough.
464 475 res.status = b'200 Script output follows'
465 476 res.headers[b'Content-Type'] = ctype
466 477 return getattr(webcommands, cmd)(rctx)
467 478
468 479 except (error.LookupError, error.RepoLookupError) as err:
469 480 msg = pycompat.bytestr(err)
470 481 if util.safehasattr(err, b'name') and not isinstance(
471 482 err, error.ManifestLookupError
472 483 ):
473 484 msg = b'revision not found: %s' % err.name
474 485
475 486 res.status = b'404 Not Found'
476 487 res.headers[b'Content-Type'] = ctype
477 488 return rctx.sendtemplate(b'error', error=msg)
478 489 except (error.RepoError, error.StorageError) as e:
479 490 res.status = b'500 Internal Server Error'
480 491 res.headers[b'Content-Type'] = ctype
481 492 return rctx.sendtemplate(b'error', error=pycompat.bytestr(e))
482 493 except error.Abort as e:
483 494 res.status = b'403 Forbidden'
484 495 res.headers[b'Content-Type'] = ctype
485 496 return rctx.sendtemplate(b'error', error=e.message)
486 497 except ErrorResponse as e:
487 498 for k, v in e.headers:
488 499 res.headers[k] = v
489 500 res.status = statusmessage(e.code, pycompat.bytestr(e))
490 501 res.headers[b'Content-Type'] = ctype
491 502 return rctx.sendtemplate(b'error', error=pycompat.bytestr(e))
492 503
493 504 def check_perm(self, rctx, req, op):
494 505 for permhook in permhooks:
495 506 permhook(rctx, req, op)
496 507
497 508
498 509 def getwebview(repo):
499 510 """The 'web.view' config controls changeset filter to hgweb. Possible
500 511 values are ``served``, ``visible`` and ``all``. Default is ``served``.
501 512 The ``served`` filter only shows changesets that can be pulled from the
502 513 hgweb instance. The``visible`` filter includes secret changesets but
503 514 still excludes "hidden" one.
504 515
505 516 See the repoview module for details.
506 517
507 518 The option has been around undocumented since Mercurial 2.5, but no
508 519 user ever asked about it. So we better keep it undocumented for now."""
509 520 # experimental config: web.view
510 521 viewconfig = repo.ui.config(b'web', b'view', untrusted=True)
511 522 if viewconfig == b'all':
512 523 return repo.unfiltered()
513 524 elif viewconfig in repoview.filtertable:
514 525 return repo.filtered(viewconfig)
515 526 else:
516 527 return repo.filtered(b'served')
@@ -1,113 +1,157 b''
1 1 ========================================================
2 2 Test the ability to access a hidden revision on a server
3 3 ========================================================
4 4
5 5 #require serve
6 6
7 7 $ . $TESTDIR/testlib/obsmarker-common.sh
8 8 $ cat >> $HGRCPATH << EOF
9 9 > [phases]
10 10 > # public changeset are not obsolete
11 11 > publish=false
12 12 > [experimental]
13 13 > evolution=all
14 14 > [ui]
15 15 > logtemplate='{rev}:{node|short} {desc} [{phase}]\n'
16 16 > EOF
17 17
18 18 Setup a simple repository with some hidden revisions
19 19 ----------------------------------------------------
20 20
21 21 Testing the `served.hidden` view
22 22
23 23 $ hg init repo-with-hidden
24 24 $ cd repo-with-hidden
25 25
26 26 $ echo 0 > a
27 27 $ hg ci -qAm "c_Public"
28 28 $ hg phase --public
29 29 $ echo 1 > a
30 30 $ hg ci -m "c_Amend_Old"
31 31 $ echo 2 > a
32 32 $ hg ci -m "c_Amend_New" --amend
33 33 $ hg up ".^"
34 34 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 35 $ echo 3 > a
36 36 $ hg ci -m "c_Pruned"
37 37 created new head
38 38 $ hg debugobsolete --record-parents `getid 'desc("c_Pruned")'` -d '0 0'
39 39 1 new obsolescence markers
40 40 obsoleted 1 changesets
41 41 $ hg up ".^"
42 42 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ echo 4 > a
44 44 $ hg ci -m "c_Secret" --secret
45 45 created new head
46 46 $ echo 5 > a
47 47 $ hg ci -m "c_Secret_Pruned" --secret
48 48 $ hg debugobsolete --record-parents `getid 'desc("c_Secret_Pruned")'` -d '0 0'
49 49 1 new obsolescence markers
50 50 obsoleted 1 changesets
51 51 $ hg up null
52 52 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
53 53
54 54 $ hg log -G -T '{rev}:{node|short} {desc} [{phase}]\n' --hidden
55 55 x 5:8d28cbe335f3 c_Secret_Pruned [secret]
56 56 |
57 57 o 4:1c6afd79eb66 c_Secret [secret]
58 58 |
59 59 | x 3:5d1575e42c25 c_Pruned [draft]
60 60 |/
61 61 | o 2:c33affeb3f6b c_Amend_New [draft]
62 62 |/
63 63 | x 1:be215fbb8c50 c_Amend_Old [draft]
64 64 |/
65 65 o 0:5f354f46e585 c_Public [public]
66 66
67 67 $ hg debugobsolete
68 68 be215fbb8c5090028b00154c1fe877ad1b376c61 c33affeb3f6b4e9621d1839d6175ddc07708807c 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'}
69 69 5d1575e42c25b7f2db75cd4e0b881b1c35158fae 0 {5f354f46e5853535841ec7a128423e991ca4d59b} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
70 70 8d28cbe335f311bc89332d7bbe8a07889b6914a0 0 {1c6afd79eb6663275bbe30097e162b1c24ced0f0} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
71 71
72 72 $ cd ..
73 73
74 74 Test the feature
75 75 ================
76 76
77 77 Check cache pre-warm
78 78 --------------------
79 79
80 80 $ ls -1 repo-with-hidden/.hg/cache
81 81 branch2
82 82 branch2-base
83 83 branch2-served
84 84 branch2-served.hidden
85 85 branch2-visible
86 86 rbc-names-v1
87 87 rbc-revs-v1
88 88 tags2
89 89 tags2-visible
90 90
91 91 Check that the `served.hidden` repoview
92 92 ---------------------------------------
93 93
94 94 $ hg -R repo-with-hidden serve -p $HGPORT -d --pid-file hg.pid --config web.view=served.hidden
95 95 $ cat hg.pid >> $DAEMON_PIDS
96 96
97 97 changesets in secret and higher phases are not visible through hgweb
98 98
99 99 $ hg -R repo-with-hidden log --template "revision: {rev}\\n" --rev "reverse(not secret())"
100 100 revision: 2
101 101 revision: 0
102 102 $ hg -R repo-with-hidden log --template "revision: {rev}\\n" --rev "reverse(not secret())" --hidden
103 103 revision: 3
104 104 revision: 2
105 105 revision: 1
106 106 revision: 0
107 107 $ get-with-headers.py localhost:$HGPORT 'log?style=raw' | grep revision:
108 108 revision: 3
109 109 revision: 2
110 110 revision: 1
111 111 revision: 0
112 112
113 113 $ killdaemons.py
114
115 Test accessing hidden changeset through hgweb
116 ---------------------------------------------
117
118 $ hg -R repo-with-hidden serve -p $HGPORT -d --pid-file hg.pid --config "experimental.server.allow-hidden-access=*" -E error.log --accesslog access.log
119 $ cat hg.pid >> $DAEMON_PIDS
120
121 Hidden changeset are hidden by default:
122
123 $ get-with-headers.py localhost:$HGPORT 'log?style=raw' | grep revision:
124 revision: 2
125 revision: 0
126
127 Hidden changeset are visible when requested:
128
129 $ get-with-headers.py localhost:$HGPORT 'log?style=raw&access-hidden=1' | grep revision:
130 revision: 3
131 revision: 2
132 revision: 1
133 revision: 0
134
135 Same check on a server that do not allow hidden access:
136 ```````````````````````````````````````````````````````
137
138 $ hg -R repo-with-hidden serve -p $HGPORT1 -d --pid-file hg2.pid --config "experimental.server.allow-hidden-access=" -E error.log --accesslog access.log
139 $ cat hg2.pid >> $DAEMON_PIDS
140
141 Hidden changeset are hidden by default:
142
143 $ get-with-headers.py localhost:$HGPORT1 'log?style=raw' | grep revision:
144 revision: 2
145 revision: 0
146
147 Hidden changeset are still hidden despite being the hidden access request:
148
149 $ get-with-headers.py localhost:$HGPORT1 'log?style=raw&access-hidden=1' | grep revision:
150 revision: 2
151 revision: 0
152
153 =============
154 Final cleanup
155 =============
156
157 $ killdaemons.py
General Comments 0
You need to be logged in to leave comments. Login now