##// END OF EJS Templates
merge: disable path conflict checking by default (issue5716)...
Siddharth Agarwal -
r34943:2a774cae stable
parent child Browse files
Show More
@@ -1,1146 +1,1146 b''
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import functools
11 11 import re
12 12
13 13 from . import (
14 14 encoding,
15 15 error,
16 16 )
17 17
18 18 def loadconfigtable(ui, extname, configtable):
19 19 """update config item known to the ui with the extension ones"""
20 20 for section, items in 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 = "extension '%s' overwrite config item '%s.%s'"
26 26 msg %= (extname, section, key)
27 27 ui.develwarn(msg, config='warn-config')
28 28
29 29 knownitems.update(items)
30 30
31 31 class configitem(object):
32 32 """represent a known config item
33 33
34 34 :section: the official config section where to find this item,
35 35 :name: the official name within the section,
36 36 :default: default value for this item,
37 37 :alias: optional list of tuples as alternatives,
38 38 :generic: this is a generic definition, match name using regular expression.
39 39 """
40 40
41 41 def __init__(self, section, name, default=None, alias=(),
42 42 generic=False, priority=0):
43 43 self.section = section
44 44 self.name = name
45 45 self.default = default
46 46 self.alias = list(alias)
47 47 self.generic = generic
48 48 self.priority = priority
49 49 self._re = None
50 50 if generic:
51 51 self._re = re.compile(self.name)
52 52
53 53 class itemregister(dict):
54 54 """A specialized dictionary that can handle wild-card selection"""
55 55
56 56 def __init__(self):
57 57 super(itemregister, self).__init__()
58 58 self._generics = set()
59 59
60 60 def update(self, other):
61 61 super(itemregister, self).update(other)
62 62 self._generics.update(other._generics)
63 63
64 64 def __setitem__(self, key, item):
65 65 super(itemregister, self).__setitem__(key, item)
66 66 if item.generic:
67 67 self._generics.add(item)
68 68
69 69 def get(self, key):
70 70 baseitem = super(itemregister, self).get(key)
71 71 if baseitem is not None and not baseitem.generic:
72 72 return baseitem
73 73
74 74 # search for a matching generic item
75 75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
76 76 for item in generics:
77 77 # we use 'match' instead of 'search' to make the matching simpler
78 78 # for people unfamiliar with regular expression. Having the match
79 79 # rooted to the start of the string will produce less surprising
80 80 # result for user writing simple regex for sub-attribute.
81 81 #
82 82 # For example using "color\..*" match produces an unsurprising
83 83 # result, while using search could suddenly match apparently
84 84 # unrelated configuration that happens to contains "color."
85 85 # anywhere. This is a tradeoff where we favor requiring ".*" on
86 86 # some match to avoid the need to prefix most pattern with "^".
87 87 # The "^" seems more error prone.
88 88 if item._re.match(key):
89 89 return item
90 90
91 91 return None
92 92
93 93 coreitems = {}
94 94
95 95 def _register(configtable, *args, **kwargs):
96 96 item = configitem(*args, **kwargs)
97 97 section = configtable.setdefault(item.section, itemregister())
98 98 if item.name in section:
99 99 msg = "duplicated config item registration for '%s.%s'"
100 100 raise error.ProgrammingError(msg % (item.section, item.name))
101 101 section[item.name] = item
102 102
103 103 # special value for case where the default is derived from other values
104 104 dynamicdefault = object()
105 105
106 106 # Registering actual config items
107 107
108 108 def getitemregister(configtable):
109 109 f = functools.partial(_register, configtable)
110 110 # export pseudo enum as configitem.*
111 111 f.dynamicdefault = dynamicdefault
112 112 return f
113 113
114 114 coreconfigitem = getitemregister(coreitems)
115 115
116 116 coreconfigitem('alias', '.*',
117 117 default=None,
118 118 generic=True,
119 119 )
120 120 coreconfigitem('annotate', 'nodates',
121 121 default=False,
122 122 )
123 123 coreconfigitem('annotate', 'showfunc',
124 124 default=False,
125 125 )
126 126 coreconfigitem('annotate', 'unified',
127 127 default=None,
128 128 )
129 129 coreconfigitem('annotate', 'git',
130 130 default=False,
131 131 )
132 132 coreconfigitem('annotate', 'ignorews',
133 133 default=False,
134 134 )
135 135 coreconfigitem('annotate', 'ignorewsamount',
136 136 default=False,
137 137 )
138 138 coreconfigitem('annotate', 'ignoreblanklines',
139 139 default=False,
140 140 )
141 141 coreconfigitem('annotate', 'ignorewseol',
142 142 default=False,
143 143 )
144 144 coreconfigitem('annotate', 'nobinary',
145 145 default=False,
146 146 )
147 147 coreconfigitem('annotate', 'noprefix',
148 148 default=False,
149 149 )
150 150 coreconfigitem('auth', 'cookiefile',
151 151 default=None,
152 152 )
153 153 # bookmarks.pushing: internal hack for discovery
154 154 coreconfigitem('bookmarks', 'pushing',
155 155 default=list,
156 156 )
157 157 # bundle.mainreporoot: internal hack for bundlerepo
158 158 coreconfigitem('bundle', 'mainreporoot',
159 159 default='',
160 160 )
161 161 # bundle.reorder: experimental config
162 162 coreconfigitem('bundle', 'reorder',
163 163 default='auto',
164 164 )
165 165 coreconfigitem('censor', 'policy',
166 166 default='abort',
167 167 )
168 168 coreconfigitem('chgserver', 'idletimeout',
169 169 default=3600,
170 170 )
171 171 coreconfigitem('chgserver', 'skiphash',
172 172 default=False,
173 173 )
174 174 coreconfigitem('cmdserver', 'log',
175 175 default=None,
176 176 )
177 177 coreconfigitem('color', '.*',
178 178 default=None,
179 179 generic=True,
180 180 )
181 181 coreconfigitem('color', 'mode',
182 182 default='auto',
183 183 )
184 184 coreconfigitem('color', 'pagermode',
185 185 default=dynamicdefault,
186 186 )
187 187 coreconfigitem('commands', 'show.aliasprefix',
188 188 default=list,
189 189 )
190 190 coreconfigitem('commands', 'status.relative',
191 191 default=False,
192 192 )
193 193 coreconfigitem('commands', 'status.skipstates',
194 194 default=[],
195 195 )
196 196 coreconfigitem('commands', 'status.verbose',
197 197 default=False,
198 198 )
199 199 coreconfigitem('commands', 'update.check',
200 200 default=None,
201 201 # Deprecated, remove after 4.4 release
202 202 alias=[('experimental', 'updatecheck')]
203 203 )
204 204 coreconfigitem('commands', 'update.requiredest',
205 205 default=False,
206 206 )
207 207 coreconfigitem('committemplate', '.*',
208 208 default=None,
209 209 generic=True,
210 210 )
211 211 coreconfigitem('debug', 'dirstate.delaywrite',
212 212 default=0,
213 213 )
214 214 coreconfigitem('defaults', '.*',
215 215 default=None,
216 216 generic=True,
217 217 )
218 218 coreconfigitem('devel', 'all-warnings',
219 219 default=False,
220 220 )
221 221 coreconfigitem('devel', 'bundle2.debug',
222 222 default=False,
223 223 )
224 224 coreconfigitem('devel', 'cache-vfs',
225 225 default=None,
226 226 )
227 227 coreconfigitem('devel', 'check-locks',
228 228 default=False,
229 229 )
230 230 coreconfigitem('devel', 'check-relroot',
231 231 default=False,
232 232 )
233 233 coreconfigitem('devel', 'default-date',
234 234 default=None,
235 235 )
236 236 coreconfigitem('devel', 'deprec-warn',
237 237 default=False,
238 238 )
239 239 coreconfigitem('devel', 'disableloaddefaultcerts',
240 240 default=False,
241 241 )
242 242 coreconfigitem('devel', 'warn-empty-changegroup',
243 243 default=False,
244 244 )
245 245 coreconfigitem('devel', 'legacy.exchange',
246 246 default=list,
247 247 )
248 248 coreconfigitem('devel', 'servercafile',
249 249 default='',
250 250 )
251 251 coreconfigitem('devel', 'serverexactprotocol',
252 252 default='',
253 253 )
254 254 coreconfigitem('devel', 'serverrequirecert',
255 255 default=False,
256 256 )
257 257 coreconfigitem('devel', 'strip-obsmarkers',
258 258 default=True,
259 259 )
260 260 coreconfigitem('devel', 'warn-config',
261 261 default=None,
262 262 )
263 263 coreconfigitem('devel', 'warn-config-default',
264 264 default=None,
265 265 )
266 266 coreconfigitem('devel', 'user.obsmarker',
267 267 default=None,
268 268 )
269 269 coreconfigitem('devel', 'warn-config-unknown',
270 270 default=None,
271 271 )
272 272 coreconfigitem('diff', 'nodates',
273 273 default=False,
274 274 )
275 275 coreconfigitem('diff', 'showfunc',
276 276 default=False,
277 277 )
278 278 coreconfigitem('diff', 'unified',
279 279 default=None,
280 280 )
281 281 coreconfigitem('diff', 'git',
282 282 default=False,
283 283 )
284 284 coreconfigitem('diff', 'ignorews',
285 285 default=False,
286 286 )
287 287 coreconfigitem('diff', 'ignorewsamount',
288 288 default=False,
289 289 )
290 290 coreconfigitem('diff', 'ignoreblanklines',
291 291 default=False,
292 292 )
293 293 coreconfigitem('diff', 'ignorewseol',
294 294 default=False,
295 295 )
296 296 coreconfigitem('diff', 'nobinary',
297 297 default=False,
298 298 )
299 299 coreconfigitem('diff', 'noprefix',
300 300 default=False,
301 301 )
302 302 coreconfigitem('email', 'bcc',
303 303 default=None,
304 304 )
305 305 coreconfigitem('email', 'cc',
306 306 default=None,
307 307 )
308 308 coreconfigitem('email', 'charsets',
309 309 default=list,
310 310 )
311 311 coreconfigitem('email', 'from',
312 312 default=None,
313 313 )
314 314 coreconfigitem('email', 'method',
315 315 default='smtp',
316 316 )
317 317 coreconfigitem('email', 'reply-to',
318 318 default=None,
319 319 )
320 320 coreconfigitem('email', 'to',
321 321 default=None,
322 322 )
323 323 coreconfigitem('experimental', 'archivemetatemplate',
324 324 default=dynamicdefault,
325 325 )
326 326 coreconfigitem('experimental', 'bundle-phases',
327 327 default=False,
328 328 )
329 329 coreconfigitem('experimental', 'bundle2-advertise',
330 330 default=True,
331 331 )
332 332 coreconfigitem('experimental', 'bundle2-output-capture',
333 333 default=False,
334 334 )
335 335 coreconfigitem('experimental', 'bundle2.pushback',
336 336 default=False,
337 337 )
338 338 coreconfigitem('experimental', 'bundle2lazylocking',
339 339 default=False,
340 340 )
341 341 coreconfigitem('experimental', 'bundlecomplevel',
342 342 default=None,
343 343 )
344 344 coreconfigitem('experimental', 'changegroup3',
345 345 default=False,
346 346 )
347 347 coreconfigitem('experimental', 'clientcompressionengines',
348 348 default=list,
349 349 )
350 350 coreconfigitem('experimental', 'copytrace',
351 351 default='on',
352 352 )
353 353 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
354 354 default=100,
355 355 )
356 356 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
357 357 default=100,
358 358 )
359 359 coreconfigitem('experimental', 'crecordtest',
360 360 default=None,
361 361 )
362 362 coreconfigitem('experimental', 'editortmpinhg',
363 363 default=False,
364 364 )
365 365 coreconfigitem('experimental', 'evolution',
366 366 default=list,
367 367 )
368 368 coreconfigitem('experimental', 'evolution.allowdivergence',
369 369 default=False,
370 370 alias=[('experimental', 'allowdivergence')]
371 371 )
372 372 coreconfigitem('experimental', 'evolution.allowunstable',
373 373 default=None,
374 374 )
375 375 coreconfigitem('experimental', 'evolution.createmarkers',
376 376 default=None,
377 377 )
378 378 coreconfigitem('experimental', 'evolution.effect-flags',
379 379 default=False,
380 380 alias=[('experimental', 'effect-flags')]
381 381 )
382 382 coreconfigitem('experimental', 'evolution.exchange',
383 383 default=None,
384 384 )
385 385 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
386 386 default=False,
387 387 )
388 388 coreconfigitem('experimental', 'evolution.track-operation',
389 389 default=True,
390 390 )
391 391 coreconfigitem('experimental', 'maxdeltachainspan',
392 392 default=-1,
393 393 )
394 394 coreconfigitem('experimental', 'mmapindexthreshold',
395 395 default=None,
396 396 )
397 397 coreconfigitem('experimental', 'nonnormalparanoidcheck',
398 398 default=False,
399 399 )
400 400 coreconfigitem('experimental', 'exportableenviron',
401 401 default=list,
402 402 )
403 403 coreconfigitem('experimental', 'extendedheader.index',
404 404 default=None,
405 405 )
406 406 coreconfigitem('experimental', 'extendedheader.similarity',
407 407 default=False,
408 408 )
409 409 coreconfigitem('experimental', 'format.compression',
410 410 default='zlib',
411 411 )
412 412 coreconfigitem('experimental', 'graphshorten',
413 413 default=False,
414 414 )
415 415 coreconfigitem('experimental', 'graphstyle.parent',
416 416 default=dynamicdefault,
417 417 )
418 418 coreconfigitem('experimental', 'graphstyle.missing',
419 419 default=dynamicdefault,
420 420 )
421 421 coreconfigitem('experimental', 'graphstyle.grandparent',
422 422 default=dynamicdefault,
423 423 )
424 424 coreconfigitem('experimental', 'hook-track-tags',
425 425 default=False,
426 426 )
427 427 coreconfigitem('experimental', 'httppostargs',
428 428 default=False,
429 429 )
430 430 coreconfigitem('experimental', 'manifestv2',
431 431 default=False,
432 432 )
433 433 coreconfigitem('experimental', 'mergedriver',
434 434 default=None,
435 435 )
436 436 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
437 437 default=False,
438 438 )
439 439 coreconfigitem('experimental', 'rebase.multidest',
440 440 default=False,
441 441 )
442 442 coreconfigitem('experimental', 'revertalternateinteractivemode',
443 443 default=True,
444 444 )
445 445 coreconfigitem('experimental', 'revlogv2',
446 446 default=None,
447 447 )
448 448 coreconfigitem('experimental', 'spacemovesdown',
449 449 default=False,
450 450 )
451 451 coreconfigitem('experimental', 'sparse-read',
452 452 default=False,
453 453 )
454 454 coreconfigitem('experimental', 'sparse-read.density-threshold',
455 455 default=0.25,
456 456 )
457 457 coreconfigitem('experimental', 'sparse-read.min-gap-size',
458 458 default='256K',
459 459 )
460 460 coreconfigitem('experimental', 'treemanifest',
461 461 default=False,
462 462 )
463 463 coreconfigitem('extensions', '.*',
464 464 default=None,
465 465 generic=True,
466 466 )
467 467 coreconfigitem('extdata', '.*',
468 468 default=None,
469 469 generic=True,
470 470 )
471 471 coreconfigitem('format', 'aggressivemergedeltas',
472 472 default=False,
473 473 )
474 474 coreconfigitem('format', 'chunkcachesize',
475 475 default=None,
476 476 )
477 477 coreconfigitem('format', 'dotencode',
478 478 default=True,
479 479 )
480 480 coreconfigitem('format', 'generaldelta',
481 481 default=False,
482 482 )
483 483 coreconfigitem('format', 'manifestcachesize',
484 484 default=None,
485 485 )
486 486 coreconfigitem('format', 'maxchainlen',
487 487 default=None,
488 488 )
489 489 coreconfigitem('format', 'obsstore-version',
490 490 default=None,
491 491 )
492 492 coreconfigitem('format', 'usefncache',
493 493 default=True,
494 494 )
495 495 coreconfigitem('format', 'usegeneraldelta',
496 496 default=True,
497 497 )
498 498 coreconfigitem('format', 'usestore',
499 499 default=True,
500 500 )
501 501 coreconfigitem('fsmonitor', 'warn_when_unused',
502 502 default=True,
503 503 )
504 504 coreconfigitem('fsmonitor', 'warn_update_file_count',
505 505 default=50000,
506 506 )
507 507 coreconfigitem('hooks', '.*',
508 508 default=dynamicdefault,
509 509 generic=True,
510 510 )
511 511 coreconfigitem('hgweb-paths', '.*',
512 512 default=list,
513 513 generic=True,
514 514 )
515 515 coreconfigitem('hostfingerprints', '.*',
516 516 default=list,
517 517 generic=True,
518 518 )
519 519 coreconfigitem('hostsecurity', 'ciphers',
520 520 default=None,
521 521 )
522 522 coreconfigitem('hostsecurity', 'disabletls10warning',
523 523 default=False,
524 524 )
525 525 coreconfigitem('hostsecurity', 'minimumprotocol',
526 526 default=dynamicdefault,
527 527 )
528 528 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
529 529 default=dynamicdefault,
530 530 generic=True,
531 531 )
532 532 coreconfigitem('hostsecurity', '.*:ciphers$',
533 533 default=dynamicdefault,
534 534 generic=True,
535 535 )
536 536 coreconfigitem('hostsecurity', '.*:fingerprints$',
537 537 default=list,
538 538 generic=True,
539 539 )
540 540 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
541 541 default=None,
542 542 generic=True,
543 543 )
544 544
545 545 coreconfigitem('http_proxy', 'always',
546 546 default=False,
547 547 )
548 548 coreconfigitem('http_proxy', 'host',
549 549 default=None,
550 550 )
551 551 coreconfigitem('http_proxy', 'no',
552 552 default=list,
553 553 )
554 554 coreconfigitem('http_proxy', 'passwd',
555 555 default=None,
556 556 )
557 557 coreconfigitem('http_proxy', 'user',
558 558 default=None,
559 559 )
560 560 coreconfigitem('logtoprocess', 'commandexception',
561 561 default=None,
562 562 )
563 563 coreconfigitem('logtoprocess', 'commandfinish',
564 564 default=None,
565 565 )
566 566 coreconfigitem('logtoprocess', 'command',
567 567 default=None,
568 568 )
569 569 coreconfigitem('logtoprocess', 'develwarn',
570 570 default=None,
571 571 )
572 572 coreconfigitem('logtoprocess', 'uiblocked',
573 573 default=None,
574 574 )
575 575 coreconfigitem('merge', 'checkunknown',
576 576 default='abort',
577 577 )
578 578 coreconfigitem('merge', 'checkignored',
579 579 default='abort',
580 580 )
581 581 coreconfigitem('experimental', 'merge.checkpathconflicts',
582 default=True,
582 default=False,
583 583 )
584 584 coreconfigitem('merge', 'followcopies',
585 585 default=True,
586 586 )
587 587 coreconfigitem('merge', 'on-failure',
588 588 default='continue',
589 589 )
590 590 coreconfigitem('merge', 'preferancestor',
591 591 default=lambda: ['*'],
592 592 )
593 593 coreconfigitem('merge-tools', '.*',
594 594 default=None,
595 595 generic=True,
596 596 )
597 597 coreconfigitem('merge-tools', br'.*\.args$',
598 598 default="$local $base $other",
599 599 generic=True,
600 600 priority=-1,
601 601 )
602 602 coreconfigitem('merge-tools', br'.*\.binary$',
603 603 default=False,
604 604 generic=True,
605 605 priority=-1,
606 606 )
607 607 coreconfigitem('merge-tools', br'.*\.check$',
608 608 default=list,
609 609 generic=True,
610 610 priority=-1,
611 611 )
612 612 coreconfigitem('merge-tools', br'.*\.checkchanged$',
613 613 default=False,
614 614 generic=True,
615 615 priority=-1,
616 616 )
617 617 coreconfigitem('merge-tools', br'.*\.executable$',
618 618 default=dynamicdefault,
619 619 generic=True,
620 620 priority=-1,
621 621 )
622 622 coreconfigitem('merge-tools', br'.*\.fixeol$',
623 623 default=False,
624 624 generic=True,
625 625 priority=-1,
626 626 )
627 627 coreconfigitem('merge-tools', br'.*\.gui$',
628 628 default=False,
629 629 generic=True,
630 630 priority=-1,
631 631 )
632 632 coreconfigitem('merge-tools', br'.*\.priority$',
633 633 default=0,
634 634 generic=True,
635 635 priority=-1,
636 636 )
637 637 coreconfigitem('merge-tools', br'.*\.premerge$',
638 638 default=dynamicdefault,
639 639 generic=True,
640 640 priority=-1,
641 641 )
642 642 coreconfigitem('merge-tools', br'.*\.symlink$',
643 643 default=False,
644 644 generic=True,
645 645 priority=-1,
646 646 )
647 647 coreconfigitem('pager', 'attend-.*',
648 648 default=dynamicdefault,
649 649 generic=True,
650 650 )
651 651 coreconfigitem('pager', 'ignore',
652 652 default=list,
653 653 )
654 654 coreconfigitem('pager', 'pager',
655 655 default=dynamicdefault,
656 656 )
657 657 coreconfigitem('patch', 'eol',
658 658 default='strict',
659 659 )
660 660 coreconfigitem('patch', 'fuzz',
661 661 default=2,
662 662 )
663 663 coreconfigitem('paths', 'default',
664 664 default=None,
665 665 )
666 666 coreconfigitem('paths', 'default-push',
667 667 default=None,
668 668 )
669 669 coreconfigitem('paths', '.*',
670 670 default=None,
671 671 generic=True,
672 672 )
673 673 coreconfigitem('phases', 'checksubrepos',
674 674 default='follow',
675 675 )
676 676 coreconfigitem('phases', 'new-commit',
677 677 default='draft',
678 678 )
679 679 coreconfigitem('phases', 'publish',
680 680 default=True,
681 681 )
682 682 coreconfigitem('profiling', 'enabled',
683 683 default=False,
684 684 )
685 685 coreconfigitem('profiling', 'format',
686 686 default='text',
687 687 )
688 688 coreconfigitem('profiling', 'freq',
689 689 default=1000,
690 690 )
691 691 coreconfigitem('profiling', 'limit',
692 692 default=30,
693 693 )
694 694 coreconfigitem('profiling', 'nested',
695 695 default=0,
696 696 )
697 697 coreconfigitem('profiling', 'output',
698 698 default=None,
699 699 )
700 700 coreconfigitem('profiling', 'showmax',
701 701 default=0.999,
702 702 )
703 703 coreconfigitem('profiling', 'showmin',
704 704 default=dynamicdefault,
705 705 )
706 706 coreconfigitem('profiling', 'sort',
707 707 default='inlinetime',
708 708 )
709 709 coreconfigitem('profiling', 'statformat',
710 710 default='hotpath',
711 711 )
712 712 coreconfigitem('profiling', 'type',
713 713 default='stat',
714 714 )
715 715 coreconfigitem('progress', 'assume-tty',
716 716 default=False,
717 717 )
718 718 coreconfigitem('progress', 'changedelay',
719 719 default=1,
720 720 )
721 721 coreconfigitem('progress', 'clear-complete',
722 722 default=True,
723 723 )
724 724 coreconfigitem('progress', 'debug',
725 725 default=False,
726 726 )
727 727 coreconfigitem('progress', 'delay',
728 728 default=3,
729 729 )
730 730 coreconfigitem('progress', 'disable',
731 731 default=False,
732 732 )
733 733 coreconfigitem('progress', 'estimateinterval',
734 734 default=60.0,
735 735 )
736 736 coreconfigitem('progress', 'format',
737 737 default=lambda: ['topic', 'bar', 'number', 'estimate'],
738 738 )
739 739 coreconfigitem('progress', 'refresh',
740 740 default=0.1,
741 741 )
742 742 coreconfigitem('progress', 'width',
743 743 default=dynamicdefault,
744 744 )
745 745 coreconfigitem('push', 'pushvars.server',
746 746 default=False,
747 747 )
748 748 coreconfigitem('server', 'bundle1',
749 749 default=True,
750 750 )
751 751 coreconfigitem('server', 'bundle1gd',
752 752 default=None,
753 753 )
754 754 coreconfigitem('server', 'bundle1.pull',
755 755 default=None,
756 756 )
757 757 coreconfigitem('server', 'bundle1gd.pull',
758 758 default=None,
759 759 )
760 760 coreconfigitem('server', 'bundle1.push',
761 761 default=None,
762 762 )
763 763 coreconfigitem('server', 'bundle1gd.push',
764 764 default=None,
765 765 )
766 766 coreconfigitem('server', 'compressionengines',
767 767 default=list,
768 768 )
769 769 coreconfigitem('server', 'concurrent-push-mode',
770 770 default='strict',
771 771 )
772 772 coreconfigitem('server', 'disablefullbundle',
773 773 default=False,
774 774 )
775 775 coreconfigitem('server', 'maxhttpheaderlen',
776 776 default=1024,
777 777 )
778 778 coreconfigitem('server', 'preferuncompressed',
779 779 default=False,
780 780 )
781 781 coreconfigitem('server', 'uncompressed',
782 782 default=True,
783 783 )
784 784 coreconfigitem('server', 'uncompressedallowsecret',
785 785 default=False,
786 786 )
787 787 coreconfigitem('server', 'validate',
788 788 default=False,
789 789 )
790 790 coreconfigitem('server', 'zliblevel',
791 791 default=-1,
792 792 )
793 793 coreconfigitem('smtp', 'host',
794 794 default=None,
795 795 )
796 796 coreconfigitem('smtp', 'local_hostname',
797 797 default=None,
798 798 )
799 799 coreconfigitem('smtp', 'password',
800 800 default=None,
801 801 )
802 802 coreconfigitem('smtp', 'port',
803 803 default=dynamicdefault,
804 804 )
805 805 coreconfigitem('smtp', 'tls',
806 806 default='none',
807 807 )
808 808 coreconfigitem('smtp', 'username',
809 809 default=None,
810 810 )
811 811 coreconfigitem('sparse', 'missingwarning',
812 812 default=True,
813 813 )
814 814 coreconfigitem('templates', '.*',
815 815 default=None,
816 816 generic=True,
817 817 )
818 818 coreconfigitem('trusted', 'groups',
819 819 default=list,
820 820 )
821 821 coreconfigitem('trusted', 'users',
822 822 default=list,
823 823 )
824 824 coreconfigitem('ui', '_usedassubrepo',
825 825 default=False,
826 826 )
827 827 coreconfigitem('ui', 'allowemptycommit',
828 828 default=False,
829 829 )
830 830 coreconfigitem('ui', 'archivemeta',
831 831 default=True,
832 832 )
833 833 coreconfigitem('ui', 'askusername',
834 834 default=False,
835 835 )
836 836 coreconfigitem('ui', 'clonebundlefallback',
837 837 default=False,
838 838 )
839 839 coreconfigitem('ui', 'clonebundleprefers',
840 840 default=list,
841 841 )
842 842 coreconfigitem('ui', 'clonebundles',
843 843 default=True,
844 844 )
845 845 coreconfigitem('ui', 'color',
846 846 default='auto',
847 847 )
848 848 coreconfigitem('ui', 'commitsubrepos',
849 849 default=False,
850 850 )
851 851 coreconfigitem('ui', 'debug',
852 852 default=False,
853 853 )
854 854 coreconfigitem('ui', 'debugger',
855 855 default=None,
856 856 )
857 857 coreconfigitem('ui', 'editor',
858 858 default=dynamicdefault,
859 859 )
860 860 coreconfigitem('ui', 'fallbackencoding',
861 861 default=None,
862 862 )
863 863 coreconfigitem('ui', 'forcecwd',
864 864 default=None,
865 865 )
866 866 coreconfigitem('ui', 'forcemerge',
867 867 default=None,
868 868 )
869 869 coreconfigitem('ui', 'formatdebug',
870 870 default=False,
871 871 )
872 872 coreconfigitem('ui', 'formatjson',
873 873 default=False,
874 874 )
875 875 coreconfigitem('ui', 'formatted',
876 876 default=None,
877 877 )
878 878 coreconfigitem('ui', 'graphnodetemplate',
879 879 default=None,
880 880 )
881 881 coreconfigitem('ui', 'http2debuglevel',
882 882 default=None,
883 883 )
884 884 coreconfigitem('ui', 'interactive',
885 885 default=None,
886 886 )
887 887 coreconfigitem('ui', 'interface',
888 888 default=None,
889 889 )
890 890 coreconfigitem('ui', 'interface.chunkselector',
891 891 default=None,
892 892 )
893 893 coreconfigitem('ui', 'logblockedtimes',
894 894 default=False,
895 895 )
896 896 coreconfigitem('ui', 'logtemplate',
897 897 default=None,
898 898 )
899 899 coreconfigitem('ui', 'merge',
900 900 default=None,
901 901 )
902 902 coreconfigitem('ui', 'mergemarkers',
903 903 default='basic',
904 904 )
905 905 coreconfigitem('ui', 'mergemarkertemplate',
906 906 default=('{node|short} '
907 907 '{ifeq(tags, "tip", "", '
908 908 'ifeq(tags, "", "", "{tags} "))}'
909 909 '{if(bookmarks, "{bookmarks} ")}'
910 910 '{ifeq(branch, "default", "", "{branch} ")}'
911 911 '- {author|user}: {desc|firstline}')
912 912 )
913 913 coreconfigitem('ui', 'nontty',
914 914 default=False,
915 915 )
916 916 coreconfigitem('ui', 'origbackuppath',
917 917 default=None,
918 918 )
919 919 coreconfigitem('ui', 'paginate',
920 920 default=True,
921 921 )
922 922 coreconfigitem('ui', 'patch',
923 923 default=None,
924 924 )
925 925 coreconfigitem('ui', 'portablefilenames',
926 926 default='warn',
927 927 )
928 928 coreconfigitem('ui', 'promptecho',
929 929 default=False,
930 930 )
931 931 coreconfigitem('ui', 'quiet',
932 932 default=False,
933 933 )
934 934 coreconfigitem('ui', 'quietbookmarkmove',
935 935 default=False,
936 936 )
937 937 coreconfigitem('ui', 'remotecmd',
938 938 default='hg',
939 939 )
940 940 coreconfigitem('ui', 'report_untrusted',
941 941 default=True,
942 942 )
943 943 coreconfigitem('ui', 'rollback',
944 944 default=True,
945 945 )
946 946 coreconfigitem('ui', 'slash',
947 947 default=False,
948 948 )
949 949 coreconfigitem('ui', 'ssh',
950 950 default='ssh',
951 951 )
952 952 coreconfigitem('ui', 'statuscopies',
953 953 default=False,
954 954 )
955 955 coreconfigitem('ui', 'strict',
956 956 default=False,
957 957 )
958 958 coreconfigitem('ui', 'style',
959 959 default='',
960 960 )
961 961 coreconfigitem('ui', 'supportcontact',
962 962 default=None,
963 963 )
964 964 coreconfigitem('ui', 'textwidth',
965 965 default=78,
966 966 )
967 967 coreconfigitem('ui', 'timeout',
968 968 default='600',
969 969 )
970 970 coreconfigitem('ui', 'traceback',
971 971 default=False,
972 972 )
973 973 coreconfigitem('ui', 'tweakdefaults',
974 974 default=False,
975 975 )
976 976 coreconfigitem('ui', 'usehttp2',
977 977 default=False,
978 978 )
979 979 coreconfigitem('ui', 'username',
980 980 alias=[('ui', 'user')]
981 981 )
982 982 coreconfigitem('ui', 'verbose',
983 983 default=False,
984 984 )
985 985 coreconfigitem('verify', 'skipflags',
986 986 default=None,
987 987 )
988 988 coreconfigitem('web', 'allowbz2',
989 989 default=False,
990 990 )
991 991 coreconfigitem('web', 'allowgz',
992 992 default=False,
993 993 )
994 994 coreconfigitem('web', 'allowpull',
995 995 default=True,
996 996 )
997 997 coreconfigitem('web', 'allow_push',
998 998 default=list,
999 999 )
1000 1000 coreconfigitem('web', 'allowzip',
1001 1001 default=False,
1002 1002 )
1003 1003 coreconfigitem('web', 'archivesubrepos',
1004 1004 default=False,
1005 1005 )
1006 1006 coreconfigitem('web', 'cache',
1007 1007 default=True,
1008 1008 )
1009 1009 coreconfigitem('web', 'contact',
1010 1010 default=None,
1011 1011 )
1012 1012 coreconfigitem('web', 'deny_push',
1013 1013 default=list,
1014 1014 )
1015 1015 coreconfigitem('web', 'guessmime',
1016 1016 default=False,
1017 1017 )
1018 1018 coreconfigitem('web', 'hidden',
1019 1019 default=False,
1020 1020 )
1021 1021 coreconfigitem('web', 'labels',
1022 1022 default=list,
1023 1023 )
1024 1024 coreconfigitem('web', 'logoimg',
1025 1025 default='hglogo.png',
1026 1026 )
1027 1027 coreconfigitem('web', 'logourl',
1028 1028 default='https://mercurial-scm.org/',
1029 1029 )
1030 1030 coreconfigitem('web', 'accesslog',
1031 1031 default='-',
1032 1032 )
1033 1033 coreconfigitem('web', 'address',
1034 1034 default='',
1035 1035 )
1036 1036 coreconfigitem('web', 'allow_archive',
1037 1037 default=list,
1038 1038 )
1039 1039 coreconfigitem('web', 'allow_read',
1040 1040 default=list,
1041 1041 )
1042 1042 coreconfigitem('web', 'baseurl',
1043 1043 default=None,
1044 1044 )
1045 1045 coreconfigitem('web', 'cacerts',
1046 1046 default=None,
1047 1047 )
1048 1048 coreconfigitem('web', 'certificate',
1049 1049 default=None,
1050 1050 )
1051 1051 coreconfigitem('web', 'collapse',
1052 1052 default=False,
1053 1053 )
1054 1054 coreconfigitem('web', 'csp',
1055 1055 default=None,
1056 1056 )
1057 1057 coreconfigitem('web', 'deny_read',
1058 1058 default=list,
1059 1059 )
1060 1060 coreconfigitem('web', 'descend',
1061 1061 default=True,
1062 1062 )
1063 1063 coreconfigitem('web', 'description',
1064 1064 default="",
1065 1065 )
1066 1066 coreconfigitem('web', 'encoding',
1067 1067 default=lambda: encoding.encoding,
1068 1068 )
1069 1069 coreconfigitem('web', 'errorlog',
1070 1070 default='-',
1071 1071 )
1072 1072 coreconfigitem('web', 'ipv6',
1073 1073 default=False,
1074 1074 )
1075 1075 coreconfigitem('web', 'maxchanges',
1076 1076 default=10,
1077 1077 )
1078 1078 coreconfigitem('web', 'maxfiles',
1079 1079 default=10,
1080 1080 )
1081 1081 coreconfigitem('web', 'maxshortchanges',
1082 1082 default=60,
1083 1083 )
1084 1084 coreconfigitem('web', 'motd',
1085 1085 default='',
1086 1086 )
1087 1087 coreconfigitem('web', 'name',
1088 1088 default=dynamicdefault,
1089 1089 )
1090 1090 coreconfigitem('web', 'port',
1091 1091 default=8000,
1092 1092 )
1093 1093 coreconfigitem('web', 'prefix',
1094 1094 default='',
1095 1095 )
1096 1096 coreconfigitem('web', 'push_ssl',
1097 1097 default=True,
1098 1098 )
1099 1099 coreconfigitem('web', 'refreshinterval',
1100 1100 default=20,
1101 1101 )
1102 1102 coreconfigitem('web', 'staticurl',
1103 1103 default=None,
1104 1104 )
1105 1105 coreconfigitem('web', 'stripes',
1106 1106 default=1,
1107 1107 )
1108 1108 coreconfigitem('web', 'style',
1109 1109 default='paper',
1110 1110 )
1111 1111 coreconfigitem('web', 'templates',
1112 1112 default=None,
1113 1113 )
1114 1114 coreconfigitem('web', 'view',
1115 1115 default='served',
1116 1116 )
1117 1117 coreconfigitem('worker', 'backgroundclose',
1118 1118 default=dynamicdefault,
1119 1119 )
1120 1120 # Windows defaults to a limit of 512 open files. A buffer of 128
1121 1121 # should give us enough headway.
1122 1122 coreconfigitem('worker', 'backgroundclosemaxqueue',
1123 1123 default=384,
1124 1124 )
1125 1125 coreconfigitem('worker', 'backgroundcloseminfilecount',
1126 1126 default=2048,
1127 1127 )
1128 1128 coreconfigitem('worker', 'backgroundclosethreadcount',
1129 1129 default=4,
1130 1130 )
1131 1131 coreconfigitem('worker', 'numcpus',
1132 1132 default=None,
1133 1133 )
1134 1134
1135 1135 # Rebase related configuration moved to core because other extension are doing
1136 1136 # strange things. For example, shelve import the extensions to reuse some bit
1137 1137 # without formally loading it.
1138 1138 coreconfigitem('commands', 'rebase.requiredest',
1139 1139 default=False,
1140 1140 )
1141 1141 coreconfigitem('experimental', 'rebaseskipobsolete',
1142 1142 default=True,
1143 1143 )
1144 1144 coreconfigitem('rebase', 'singletransaction',
1145 1145 default=False,
1146 1146 )
@@ -1,248 +1,237 b''
1 1 $ hg init
2 2
3 3 audit of .hg
4 4
5 5 $ hg add .hg/00changelog.i
6 6 abort: path contains illegal component: .hg/00changelog.i (glob)
7 7 [255]
8 8
9 9 #if symlink
10 10
11 11 Symlinks
12 12
13 13 $ mkdir a
14 14 $ echo a > a/a
15 15 $ hg ci -Ama
16 16 adding a/a
17 17 $ ln -s a b
18 18 $ echo b > a/b
19 19 $ hg add b/b
20 20 abort: path 'b/b' traverses symbolic link 'b' (glob)
21 21 [255]
22 22 $ hg add b
23 23
24 24 should still fail - maybe
25 25
26 26 $ hg add b/b
27 27 abort: path 'b/b' traverses symbolic link 'b' (glob)
28 28 [255]
29 29
30 30 $ hg commit -m 'add symlink b'
31 31
32 32
33 33 Test symlink traversing when accessing history:
34 34 -----------------------------------------------
35 35
36 36 (build a changeset where the path exists as a directory)
37 37
38 38 $ hg up 0
39 39 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
40 40 $ mkdir b
41 41 $ echo c > b/a
42 42 $ hg add b/a
43 43 $ hg ci -m 'add directory b'
44 44 created new head
45 45
46 46 Test that hg cat does not do anything wrong the working copy has 'b' as directory
47 47
48 48 $ hg cat b/a
49 49 c
50 50 $ hg cat -r "desc(directory)" b/a
51 51 c
52 52 $ hg cat -r "desc(symlink)" b/a
53 53 b/a: no such file in rev bc151a1f53bd
54 54 [1]
55 55
56 56 Test that hg cat does not do anything wrong the working copy has 'b' as a symlink (issue4749)
57 57
58 58 $ hg up 'desc(symlink)'
59 59 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
60 60 $ hg cat b/a
61 61 b/a: no such file in rev bc151a1f53bd
62 62 [1]
63 63 $ hg cat -r "desc(directory)" b/a
64 64 c
65 65 $ hg cat -r "desc(symlink)" b/a
66 66 b/a: no such file in rev bc151a1f53bd
67 67 [1]
68 68
69 69 #endif
70 70
71 71
72 72 unbundle tampered bundle
73 73
74 74 $ hg init target
75 75 $ cd target
76 76 $ hg unbundle "$TESTDIR/bundles/tampered.hg"
77 77 adding changesets
78 78 adding manifests
79 79 adding file changes
80 80 added 5 changesets with 6 changes to 6 files (+4 heads)
81 81 new changesets b7da9bf6b037:fc1393d727bc
82 82 (run 'hg heads' to see heads, 'hg merge' to merge)
83 83
84 84 attack .hg/test
85 85
86 86 $ hg manifest -r0
87 87 .hg/test
88 88 $ hg update -Cr0
89 89 abort: path contains illegal component: .hg/test (glob)
90 90 [255]
91 91
92 92 attack foo/.hg/test
93 93
94 94 $ hg manifest -r1
95 95 foo/.hg/test
96 96 $ hg update -Cr1
97 97 abort: path 'foo/.hg/test' is inside nested repo 'foo' (glob)
98 98 [255]
99 99
100 100 attack back/test where back symlinks to ..
101 101
102 102 $ hg manifest -r2
103 103 back
104 104 back/test
105 105 #if symlink
106 106 $ hg update -Cr2
107 back: is both a file and a directory
108 abort: destination manifest contains path conflicts
107 abort: path 'back/test' traverses symbolic link 'back'
109 108 [255]
110 109 #else
111 110 ('back' will be a file and cause some other system specific error)
112 111 $ hg update -Cr2
113 112 back: is both a file and a directory
114 113 abort: * (glob)
115 114 [255]
116 115 #endif
117 116
118 117 attack ../test
119 118
120 119 $ hg manifest -r3
121 120 ../test
122 121 $ mkdir ../test
123 122 $ echo data > ../test/file
124 123 $ hg update -Cr3
125 124 abort: path contains illegal component: ../test (glob)
126 125 [255]
127 126 $ cat ../test/file
128 127 data
129 128
130 129 attack /tmp/test
131 130
132 131 $ hg manifest -r4
133 132 /tmp/test
134 133 $ hg update -Cr4
135 134 abort: path contains illegal component: /tmp/test (glob)
136 135 [255]
137 136
138 137 $ cd ..
139 138
140 139 Test symlink traversal on merge:
141 140 --------------------------------
142 141
143 142 #if symlink
144 143
145 144 set up symlink hell
146 145
147 146 $ mkdir merge-symlink-out
148 147 $ hg init merge-symlink
149 148 $ cd merge-symlink
150 149 $ touch base
151 150 $ hg commit -qAm base
152 151 $ ln -s ../merge-symlink-out a
153 152 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
154 153 $ hg up -q 0
155 154 $ mkdir a
156 155 $ touch a/poisoned
157 156 $ hg commit -qAm 'file a/poisoned'
158 157 $ hg log -G -T '{rev}: {desc}\n'
159 158 @ 2: file a/poisoned
160 159 |
161 160 | o 1: symlink a -> ../merge-symlink-out
162 161 |/
163 162 o 0: base
164 163
165 164
166 165 try trivial merge
167 166
168 167 $ hg up -qC 1
169 168 $ hg merge 2
170 a: path conflict - a file or link has the same name as a directory
171 the local file has been renamed to a~aa04623eb0c3
172 resolve manually then use 'hg resolve --mark a'
173 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
174 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
175 [1]
169 abort: path 'a/poisoned' traverses symbolic link 'a'
170 [255]
176 171
177 172 try rebase onto other revision: cache of audited paths should be discarded,
178 173 and the rebase should fail (issue5628)
179 174
180 175 $ hg up -qC 2
181 176 $ hg rebase -s 2 -d 1 --config extensions.rebase=
182 177 rebasing 2:e73c21d6b244 "file a/poisoned" (tip)
183 a: path conflict - a file or link has the same name as a directory
184 the local file has been renamed to a~aa04623eb0c3
185 resolve manually then use 'hg resolve --mark a'
186 unresolved conflicts (see hg resolve, then hg rebase --continue)
187 [1]
178 abort: path 'a/poisoned' traverses symbolic link 'a'
179 [255]
188 180 $ ls ../merge-symlink-out
189 181
190 182 $ cd ..
191 183
192 184 Test symlink traversal on update:
193 185 ---------------------------------
194 186
195 187 $ mkdir update-symlink-out
196 188 $ hg init update-symlink
197 189 $ cd update-symlink
198 190 $ ln -s ../update-symlink-out a
199 191 $ hg commit -qAm 'symlink a -> ../update-symlink-out'
200 192 $ hg rm a
201 193 $ mkdir a && touch a/b
202 194 $ hg ci -qAm 'file a/b' a/b
203 195 $ hg up -qC 0
204 196 $ hg rm a
205 197 $ mkdir a && touch a/c
206 198 $ hg ci -qAm 'rm a, file a/c'
207 199 $ hg log -G -T '{rev}: {desc}\n'
208 200 @ 2: rm a, file a/c
209 201 |
210 202 | o 1: file a/b
211 203 |/
212 204 o 0: symlink a -> ../update-symlink-out
213 205
214 206
215 207 try linear update where symlink already exists:
216 208
217 209 $ hg up -qC 0
218 210 $ hg up 1
219 a: is both a file and a directory
220 abort: destination manifest contains path conflicts
211 abort: path 'a/b' traverses symbolic link 'a'
221 212 [255]
222 213
223 214 try linear update including symlinked directory and its content: paths are
224 215 audited first by calculateupdates(), where no symlink is created so both
225 216 'a' and 'a/b' are taken as good paths. still applyupdates() should fail.
226 217
227 218 $ hg up -qC null
228 219 $ hg up 1
229 a: is both a file and a directory
230 abort: destination manifest contains path conflicts
220 abort: path 'a/b' traverses symbolic link 'a'
231 221 [255]
232 222 $ ls ../update-symlink-out
233 223
234 224 try branch update replacing directory with symlink, and its content: the
235 225 path 'a' is audited as a directory first, which should be audited again as
236 226 a symlink.
237 227
238 228 $ rm -f a
239 229 $ hg up -qC 2
240 230 $ hg up 1
241 a: is both a file and a directory
242 abort: destination manifest contains path conflicts
231 abort: path 'a/b' traverses symbolic link 'a'
243 232 [255]
244 233 $ ls ../update-symlink-out
245 234
246 235 $ cd ..
247 236
248 237 #endif
@@ -1,1013 +1,1009 b''
1 1 #if windows
2 2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
3 3 #else
4 4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
5 5 #endif
6 6 $ export PYTHONPATH
7 7
8 8 typical client does not want echo-back messages, so test without it:
9 9
10 10 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
11 11 $ mv $HGRCPATH.new $HGRCPATH
12 12
13 13 $ hg init repo
14 14 $ cd repo
15 15
16 16 >>> from __future__ import absolute_import, print_function
17 17 >>> import os
18 18 >>> import sys
19 19 >>> from hgclient import check, readchannel, runcommand
20 20 >>> @check
21 21 ... def hellomessage(server):
22 22 ... ch, data = readchannel(server)
23 23 ... print('%c, %r' % (ch, data))
24 24 ... # run an arbitrary command to make sure the next thing the server
25 25 ... # sends isn't part of the hello message
26 26 ... runcommand(server, ['id'])
27 27 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
28 28 *** runcommand id
29 29 000000000000 tip
30 30
31 31 >>> from hgclient import check
32 32 >>> @check
33 33 ... def unknowncommand(server):
34 34 ... server.stdin.write('unknowncommand\n')
35 35 abort: unknown command unknowncommand
36 36
37 37 >>> from hgclient import check, readchannel, runcommand
38 38 >>> @check
39 39 ... def checkruncommand(server):
40 40 ... # hello block
41 41 ... readchannel(server)
42 42 ...
43 43 ... # no args
44 44 ... runcommand(server, [])
45 45 ...
46 46 ... # global options
47 47 ... runcommand(server, ['id', '--quiet'])
48 48 ...
49 49 ... # make sure global options don't stick through requests
50 50 ... runcommand(server, ['id'])
51 51 ...
52 52 ... # --config
53 53 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
54 54 ...
55 55 ... # make sure --config doesn't stick
56 56 ... runcommand(server, ['id'])
57 57 ...
58 58 ... # negative return code should be masked
59 59 ... runcommand(server, ['id', '-runknown'])
60 60 *** runcommand
61 61 Mercurial Distributed SCM
62 62
63 63 basic commands:
64 64
65 65 add add the specified files on the next commit
66 66 annotate show changeset information by line for each file
67 67 clone make a copy of an existing repository
68 68 commit commit the specified files or all outstanding changes
69 69 diff diff repository (or selected files)
70 70 export dump the header and diffs for one or more changesets
71 71 forget forget the specified files on the next commit
72 72 init create a new repository in the given directory
73 73 log show revision history of entire repository or files
74 74 merge merge another revision into working directory
75 75 pull pull changes from the specified source
76 76 push push changes to the specified destination
77 77 remove remove the specified files on the next commit
78 78 serve start stand-alone webserver
79 79 status show changed files in the working directory
80 80 summary summarize working directory state
81 81 update update working directory (or switch revisions)
82 82
83 83 (use 'hg help' for the full list of commands or 'hg -v' for details)
84 84 *** runcommand id --quiet
85 85 000000000000
86 86 *** runcommand id
87 87 000000000000 tip
88 88 *** runcommand id --config ui.quiet=True
89 89 000000000000
90 90 *** runcommand id
91 91 000000000000 tip
92 92 *** runcommand id -runknown
93 93 abort: unknown revision 'unknown'!
94 94 [255]
95 95
96 96 >>> from hgclient import check, readchannel
97 97 >>> @check
98 98 ... def inputeof(server):
99 99 ... readchannel(server)
100 100 ... server.stdin.write('runcommand\n')
101 101 ... # close stdin while server is waiting for input
102 102 ... server.stdin.close()
103 103 ...
104 104 ... # server exits with 1 if the pipe closed while reading the command
105 105 ... print('server exit code =', server.wait())
106 106 server exit code = 1
107 107
108 108 >>> from hgclient import check, readchannel, runcommand, stringio
109 109 >>> @check
110 110 ... def serverinput(server):
111 111 ... readchannel(server)
112 112 ...
113 113 ... patch = """
114 114 ... # HG changeset patch
115 115 ... # User test
116 116 ... # Date 0 0
117 117 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
118 118 ... # Parent 0000000000000000000000000000000000000000
119 119 ... 1
120 120 ...
121 121 ... diff -r 000000000000 -r c103a3dec114 a
122 122 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123 123 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
124 124 ... @@ -0,0 +1,1 @@
125 125 ... +1
126 126 ... """
127 127 ...
128 128 ... runcommand(server, ['import', '-'], input=stringio(patch))
129 129 ... runcommand(server, ['log'])
130 130 *** runcommand import -
131 131 applying patch from stdin
132 132 *** runcommand log
133 133 changeset: 0:eff892de26ec
134 134 tag: tip
135 135 user: test
136 136 date: Thu Jan 01 00:00:00 1970 +0000
137 137 summary: 1
138 138
139 139
140 140 check that "histedit --commands=-" can read rules from the input channel:
141 141
142 142 >>> import cStringIO
143 143 >>> from hgclient import check, readchannel, runcommand
144 144 >>> @check
145 145 ... def serverinput(server):
146 146 ... readchannel(server)
147 147 ... rules = 'pick eff892de26ec\n'
148 148 ... runcommand(server, ['histedit', '0', '--commands=-',
149 149 ... '--config', 'extensions.histedit='],
150 150 ... input=cStringIO.StringIO(rules))
151 151 *** runcommand histedit 0 --commands=- --config extensions.histedit=
152 152
153 153 check that --cwd doesn't persist between requests:
154 154
155 155 $ mkdir foo
156 156 $ touch foo/bar
157 157 >>> from hgclient import check, readchannel, runcommand
158 158 >>> @check
159 159 ... def cwd(server):
160 160 ... readchannel(server)
161 161 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
162 162 ... runcommand(server, ['st', 'foo/bar'])
163 163 *** runcommand --cwd foo st bar
164 164 ? bar
165 165 *** runcommand st foo/bar
166 166 ? foo/bar
167 167
168 168 $ rm foo/bar
169 169
170 170
171 171 check that local configs for the cached repo aren't inherited when -R is used:
172 172
173 173 $ cat <<EOF >> .hg/hgrc
174 174 > [ui]
175 175 > foo = bar
176 176 > EOF
177 177
178 178 >>> from hgclient import check, readchannel, runcommand, sep
179 179 >>> @check
180 180 ... def localhgrc(server):
181 181 ... readchannel(server)
182 182 ...
183 183 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
184 184 ... # show it
185 185 ... runcommand(server, ['showconfig'], outfilter=sep)
186 186 ...
187 187 ... # but not for this repo
188 188 ... runcommand(server, ['init', 'foo'])
189 189 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
190 190 *** runcommand showconfig
191 191 bundle.mainreporoot=$TESTTMP/repo
192 192 devel.all-warnings=true
193 193 devel.default-date=0 0
194 194 extensions.fsmonitor= (fsmonitor !)
195 195 largefiles.usercache=$TESTTMP/.cache/largefiles
196 196 ui.slash=True
197 197 ui.interactive=False
198 198 ui.mergemarkers=detailed
199 199 ui.usehttp2=true (?)
200 200 ui.foo=bar
201 201 ui.nontty=true
202 202 web.address=localhost
203 203 web\.ipv6=(?:True|False) (re)
204 204 *** runcommand init foo
205 205 *** runcommand -R foo showconfig ui defaults
206 206 ui.slash=True
207 207 ui.interactive=False
208 208 ui.mergemarkers=detailed
209 209 ui.usehttp2=true (?)
210 210 ui.nontty=true
211 211
212 212 $ rm -R foo
213 213
214 214 #if windows
215 215 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
216 216 #else
217 217 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
218 218 #endif
219 219
220 220 $ cat <<EOF > hook.py
221 221 > from __future__ import print_function
222 222 > import sys
223 223 > def hook(**args):
224 224 > print('hook talking')
225 225 > print('now try to read something: %r' % sys.stdin.read())
226 226 > EOF
227 227
228 228 >>> from hgclient import check, readchannel, runcommand, stringio
229 229 >>> @check
230 230 ... def hookoutput(server):
231 231 ... readchannel(server)
232 232 ... runcommand(server, ['--config',
233 233 ... 'hooks.pre-identify=python:hook.hook',
234 234 ... 'id'],
235 235 ... input=stringio('some input'))
236 236 *** runcommand --config hooks.pre-identify=python:hook.hook id
237 237 eff892de26ec tip
238 238
239 239 Clean hook cached version
240 240 $ rm hook.py*
241 241 $ rm -Rf __pycache__
242 242
243 243 $ echo a >> a
244 244 >>> import os
245 245 >>> from hgclient import check, readchannel, runcommand
246 246 >>> @check
247 247 ... def outsidechanges(server):
248 248 ... readchannel(server)
249 249 ... runcommand(server, ['status'])
250 250 ... os.system('hg ci -Am2')
251 251 ... runcommand(server, ['tip'])
252 252 ... runcommand(server, ['status'])
253 253 *** runcommand status
254 254 M a
255 255 *** runcommand tip
256 256 changeset: 1:d3a0a68be6de
257 257 tag: tip
258 258 user: test
259 259 date: Thu Jan 01 00:00:00 1970 +0000
260 260 summary: 2
261 261
262 262 *** runcommand status
263 263
264 264 >>> import os
265 265 >>> from hgclient import check, readchannel, runcommand
266 266 >>> @check
267 267 ... def bookmarks(server):
268 268 ... readchannel(server)
269 269 ... runcommand(server, ['bookmarks'])
270 270 ...
271 271 ... # changes .hg/bookmarks
272 272 ... os.system('hg bookmark -i bm1')
273 273 ... os.system('hg bookmark -i bm2')
274 274 ... runcommand(server, ['bookmarks'])
275 275 ...
276 276 ... # changes .hg/bookmarks.current
277 277 ... os.system('hg upd bm1 -q')
278 278 ... runcommand(server, ['bookmarks'])
279 279 ...
280 280 ... runcommand(server, ['bookmarks', 'bm3'])
281 281 ... f = open('a', 'ab')
282 282 ... f.write('a\n')
283 283 ... f.close()
284 284 ... runcommand(server, ['commit', '-Amm'])
285 285 ... runcommand(server, ['bookmarks'])
286 286 ... print('')
287 287 *** runcommand bookmarks
288 288 no bookmarks set
289 289 *** runcommand bookmarks
290 290 bm1 1:d3a0a68be6de
291 291 bm2 1:d3a0a68be6de
292 292 *** runcommand bookmarks
293 293 * bm1 1:d3a0a68be6de
294 294 bm2 1:d3a0a68be6de
295 295 *** runcommand bookmarks bm3
296 296 *** runcommand commit -Amm
297 297 *** runcommand bookmarks
298 298 bm1 1:d3a0a68be6de
299 299 bm2 1:d3a0a68be6de
300 300 * bm3 2:aef17e88f5f0
301 301
302 302
303 303 >>> import os
304 304 >>> from hgclient import check, readchannel, runcommand
305 305 >>> @check
306 306 ... def tagscache(server):
307 307 ... readchannel(server)
308 308 ... runcommand(server, ['id', '-t', '-r', '0'])
309 309 ... os.system('hg tag -r 0 foo')
310 310 ... runcommand(server, ['id', '-t', '-r', '0'])
311 311 *** runcommand id -t -r 0
312 312
313 313 *** runcommand id -t -r 0
314 314 foo
315 315
316 316 >>> import os
317 317 >>> from hgclient import check, readchannel, runcommand
318 318 >>> @check
319 319 ... def setphase(server):
320 320 ... readchannel(server)
321 321 ... runcommand(server, ['phase', '-r', '.'])
322 322 ... os.system('hg phase -r . -p')
323 323 ... runcommand(server, ['phase', '-r', '.'])
324 324 *** runcommand phase -r .
325 325 3: draft
326 326 *** runcommand phase -r .
327 327 3: public
328 328
329 329 $ echo a >> a
330 330 >>> from hgclient import check, readchannel, runcommand
331 331 >>> @check
332 332 ... def rollback(server):
333 333 ... readchannel(server)
334 334 ... runcommand(server, ['phase', '-r', '.', '-p'])
335 335 ... runcommand(server, ['commit', '-Am.'])
336 336 ... runcommand(server, ['rollback'])
337 337 ... runcommand(server, ['phase', '-r', '.'])
338 338 ... print('')
339 339 *** runcommand phase -r . -p
340 340 no phases changed
341 341 *** runcommand commit -Am.
342 342 *** runcommand rollback
343 343 repository tip rolled back to revision 3 (undo commit)
344 344 working directory now based on revision 3
345 345 *** runcommand phase -r .
346 346 3: public
347 347
348 348
349 349 >>> import os
350 350 >>> from hgclient import check, readchannel, runcommand
351 351 >>> @check
352 352 ... def branch(server):
353 353 ... readchannel(server)
354 354 ... runcommand(server, ['branch'])
355 355 ... os.system('hg branch foo')
356 356 ... runcommand(server, ['branch'])
357 357 ... os.system('hg branch default')
358 358 *** runcommand branch
359 359 default
360 360 marked working directory as branch foo
361 361 (branches are permanent and global, did you want a bookmark?)
362 362 *** runcommand branch
363 363 foo
364 364 marked working directory as branch default
365 365 (branches are permanent and global, did you want a bookmark?)
366 366
367 367 $ touch .hgignore
368 368 >>> import os
369 369 >>> from hgclient import check, readchannel, runcommand
370 370 >>> @check
371 371 ... def hgignore(server):
372 372 ... readchannel(server)
373 373 ... runcommand(server, ['commit', '-Am.'])
374 374 ... f = open('ignored-file', 'ab')
375 375 ... f.write('')
376 376 ... f.close()
377 377 ... f = open('.hgignore', 'ab')
378 378 ... f.write('ignored-file')
379 379 ... f.close()
380 380 ... runcommand(server, ['status', '-i', '-u'])
381 381 ... print('')
382 382 *** runcommand commit -Am.
383 383 adding .hgignore
384 384 *** runcommand status -i -u
385 385 I ignored-file
386 386
387 387
388 388 cache of non-public revisions should be invalidated on repository change
389 389 (issue4855):
390 390
391 391 >>> import os
392 392 >>> from hgclient import check, readchannel, runcommand
393 393 >>> @check
394 394 ... def phasesetscacheaftercommit(server):
395 395 ... readchannel(server)
396 396 ... # load _phasecache._phaserevs and _phasesets
397 397 ... runcommand(server, ['log', '-qr', 'draft()'])
398 398 ... # create draft commits by another process
399 399 ... for i in xrange(5, 7):
400 400 ... f = open('a', 'ab')
401 401 ... f.seek(0, os.SEEK_END)
402 402 ... f.write('a\n')
403 403 ... f.close()
404 404 ... os.system('hg commit -Aqm%d' % i)
405 405 ... # new commits should be listed as draft revisions
406 406 ... runcommand(server, ['log', '-qr', 'draft()'])
407 407 ... print('')
408 408 *** runcommand log -qr draft()
409 409 4:7966c8e3734d
410 410 *** runcommand log -qr draft()
411 411 4:7966c8e3734d
412 412 5:41f6602d1c4f
413 413 6:10501e202c35
414 414
415 415
416 416 >>> import os
417 417 >>> from hgclient import check, readchannel, runcommand
418 418 >>> @check
419 419 ... def phasesetscacheafterstrip(server):
420 420 ... readchannel(server)
421 421 ... # load _phasecache._phaserevs and _phasesets
422 422 ... runcommand(server, ['log', '-qr', 'draft()'])
423 423 ... # strip cached revisions by another process
424 424 ... os.system('hg --config extensions.strip= strip -q 5')
425 425 ... # shouldn't abort by "unknown revision '6'"
426 426 ... runcommand(server, ['log', '-qr', 'draft()'])
427 427 ... print('')
428 428 *** runcommand log -qr draft()
429 429 4:7966c8e3734d
430 430 5:41f6602d1c4f
431 431 6:10501e202c35
432 432 *** runcommand log -qr draft()
433 433 4:7966c8e3734d
434 434
435 435
436 436 cache of phase roots should be invalidated on strip (issue3827):
437 437
438 438 >>> import os
439 439 >>> from hgclient import check, readchannel, runcommand, sep
440 440 >>> @check
441 441 ... def phasecacheafterstrip(server):
442 442 ... readchannel(server)
443 443 ...
444 444 ... # create new head, 5:731265503d86
445 445 ... runcommand(server, ['update', '-C', '0'])
446 446 ... f = open('a', 'ab')
447 447 ... f.write('a\n')
448 448 ... f.close()
449 449 ... runcommand(server, ['commit', '-Am.', 'a'])
450 450 ... runcommand(server, ['log', '-Gq'])
451 451 ...
452 452 ... # make it public; draft marker moves to 4:7966c8e3734d
453 453 ... runcommand(server, ['phase', '-p', '.'])
454 454 ... # load _phasecache.phaseroots
455 455 ... runcommand(server, ['phase', '.'], outfilter=sep)
456 456 ...
457 457 ... # strip 1::4 outside server
458 458 ... os.system('hg -q --config extensions.mq= strip 1')
459 459 ...
460 460 ... # shouldn't raise "7966c8e3734d: no node!"
461 461 ... runcommand(server, ['branches'])
462 462 *** runcommand update -C 0
463 463 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
464 464 (leaving bookmark bm3)
465 465 *** runcommand commit -Am. a
466 466 created new head
467 467 *** runcommand log -Gq
468 468 @ 5:731265503d86
469 469 |
470 470 | o 4:7966c8e3734d
471 471 | |
472 472 | o 3:b9b85890c400
473 473 | |
474 474 | o 2:aef17e88f5f0
475 475 | |
476 476 | o 1:d3a0a68be6de
477 477 |/
478 478 o 0:eff892de26ec
479 479
480 480 *** runcommand phase -p .
481 481 *** runcommand phase .
482 482 5: public
483 483 *** runcommand branches
484 484 default 1:731265503d86
485 485
486 486 in-memory cache must be reloaded if transaction is aborted. otherwise
487 487 changelog and manifest would have invalid node:
488 488
489 489 $ echo a >> a
490 490 >>> from hgclient import check, readchannel, runcommand
491 491 >>> @check
492 492 ... def txabort(server):
493 493 ... readchannel(server)
494 494 ... runcommand(server, ['commit', '--config', 'hooks.pretxncommit=false',
495 495 ... '-mfoo'])
496 496 ... runcommand(server, ['verify'])
497 497 *** runcommand commit --config hooks.pretxncommit=false -mfoo
498 498 transaction abort!
499 499 rollback completed
500 500 abort: pretxncommit hook exited with status 1
501 501 [255]
502 502 *** runcommand verify
503 503 checking changesets
504 504 checking manifests
505 505 crosschecking files in changesets and manifests
506 506 checking files
507 507 1 files, 2 changesets, 2 total revisions
508 508 $ hg revert --no-backup -aq
509 509
510 510 $ cat >> .hg/hgrc << EOF
511 511 > [experimental]
512 512 > evolution.createmarkers=True
513 513 > EOF
514 514
515 515 >>> import os
516 516 >>> from hgclient import check, readchannel, runcommand
517 517 >>> @check
518 518 ... def obsolete(server):
519 519 ... readchannel(server)
520 520 ...
521 521 ... runcommand(server, ['up', 'null'])
522 522 ... runcommand(server, ['phase', '-df', 'tip'])
523 523 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
524 524 ... if os.name == 'nt':
525 525 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
526 526 ... os.system(cmd)
527 527 ... runcommand(server, ['log', '--hidden'])
528 528 ... runcommand(server, ['log'])
529 529 *** runcommand up null
530 530 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
531 531 *** runcommand phase -df tip
532 532 obsoleted 1 changesets
533 533 *** runcommand log --hidden
534 534 changeset: 1:731265503d86
535 535 tag: tip
536 536 user: test
537 537 date: Thu Jan 01 00:00:00 1970 +0000
538 538 obsolete: pruned
539 539 summary: .
540 540
541 541 changeset: 0:eff892de26ec
542 542 bookmark: bm1
543 543 bookmark: bm2
544 544 bookmark: bm3
545 545 user: test
546 546 date: Thu Jan 01 00:00:00 1970 +0000
547 547 summary: 1
548 548
549 549 *** runcommand log
550 550 changeset: 0:eff892de26ec
551 551 bookmark: bm1
552 552 bookmark: bm2
553 553 bookmark: bm3
554 554 tag: tip
555 555 user: test
556 556 date: Thu Jan 01 00:00:00 1970 +0000
557 557 summary: 1
558 558
559 559
560 560 $ cat <<EOF >> .hg/hgrc
561 561 > [extensions]
562 562 > mq =
563 563 > EOF
564 564
565 565 >>> import os
566 566 >>> from hgclient import check, readchannel, runcommand
567 567 >>> @check
568 568 ... def mqoutsidechanges(server):
569 569 ... readchannel(server)
570 570 ...
571 571 ... # load repo.mq
572 572 ... runcommand(server, ['qapplied'])
573 573 ... os.system('hg qnew 0.diff')
574 574 ... # repo.mq should be invalidated
575 575 ... runcommand(server, ['qapplied'])
576 576 ...
577 577 ... runcommand(server, ['qpop', '--all'])
578 578 ... os.system('hg qqueue --create foo')
579 579 ... # repo.mq should be recreated to point to new queue
580 580 ... runcommand(server, ['qqueue', '--active'])
581 581 *** runcommand qapplied
582 582 *** runcommand qapplied
583 583 0.diff
584 584 *** runcommand qpop --all
585 585 popping 0.diff
586 586 patch queue now empty
587 587 *** runcommand qqueue --active
588 588 foo
589 589
590 590 $ cat <<EOF > dbgui.py
591 591 > import os
592 592 > import sys
593 593 > from mercurial import commands, registrar
594 594 > cmdtable = {}
595 595 > command = registrar.command(cmdtable)
596 596 > @command(b"debuggetpass", norepo=True)
597 597 > def debuggetpass(ui):
598 598 > ui.write("%s\\n" % ui.getpass())
599 599 > @command(b"debugprompt", norepo=True)
600 600 > def debugprompt(ui):
601 601 > ui.write("%s\\n" % ui.prompt("prompt:"))
602 602 > @command(b"debugreadstdin", norepo=True)
603 603 > def debugreadstdin(ui):
604 604 > ui.write("read: %r\n" % sys.stdin.read(1))
605 605 > @command(b"debugwritestdout", norepo=True)
606 606 > def debugwritestdout(ui):
607 607 > os.write(1, "low-level stdout fd and\n")
608 608 > sys.stdout.write("stdout should be redirected to /dev/null\n")
609 609 > sys.stdout.flush()
610 610 > EOF
611 611 $ cat <<EOF >> .hg/hgrc
612 612 > [extensions]
613 613 > dbgui = dbgui.py
614 614 > EOF
615 615
616 616 >>> from hgclient import check, readchannel, runcommand, stringio
617 617 >>> @check
618 618 ... def getpass(server):
619 619 ... readchannel(server)
620 620 ... runcommand(server, ['debuggetpass', '--config',
621 621 ... 'ui.interactive=True'],
622 622 ... input=stringio('1234\n'))
623 623 ... runcommand(server, ['debuggetpass', '--config',
624 624 ... 'ui.interactive=True'],
625 625 ... input=stringio('\n'))
626 626 ... runcommand(server, ['debuggetpass', '--config',
627 627 ... 'ui.interactive=True'],
628 628 ... input=stringio(''))
629 629 ... runcommand(server, ['debugprompt', '--config',
630 630 ... 'ui.interactive=True'],
631 631 ... input=stringio('5678\n'))
632 632 ... runcommand(server, ['debugreadstdin'])
633 633 ... runcommand(server, ['debugwritestdout'])
634 634 *** runcommand debuggetpass --config ui.interactive=True
635 635 password: 1234
636 636 *** runcommand debuggetpass --config ui.interactive=True
637 637 password:
638 638 *** runcommand debuggetpass --config ui.interactive=True
639 639 password: abort: response expected
640 640 [255]
641 641 *** runcommand debugprompt --config ui.interactive=True
642 642 prompt: 5678
643 643 *** runcommand debugreadstdin
644 644 read: ''
645 645 *** runcommand debugwritestdout
646 646
647 647
648 648 run commandserver in commandserver, which is silly but should work:
649 649
650 650 >>> from __future__ import print_function
651 651 >>> from hgclient import check, readchannel, runcommand, stringio
652 652 >>> @check
653 653 ... def nested(server):
654 654 ... print('%c, %r' % readchannel(server))
655 655 ... class nestedserver(object):
656 656 ... stdin = stringio('getencoding\n')
657 657 ... stdout = stringio()
658 658 ... runcommand(server, ['serve', '--cmdserver', 'pipe'],
659 659 ... output=nestedserver.stdout, input=nestedserver.stdin)
660 660 ... nestedserver.stdout.seek(0)
661 661 ... print('%c, %r' % readchannel(nestedserver)) # hello
662 662 ... print('%c, %r' % readchannel(nestedserver)) # getencoding
663 663 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
664 664 *** runcommand serve --cmdserver pipe
665 665 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
666 666 r, '*' (glob)
667 667
668 668
669 669 start without repository:
670 670
671 671 $ cd ..
672 672
673 673 >>> from __future__ import print_function
674 674 >>> from hgclient import check, readchannel, runcommand
675 675 >>> @check
676 676 ... def hellomessage(server):
677 677 ... ch, data = readchannel(server)
678 678 ... print('%c, %r' % (ch, data))
679 679 ... # run an arbitrary command to make sure the next thing the server
680 680 ... # sends isn't part of the hello message
681 681 ... runcommand(server, ['id'])
682 682 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
683 683 *** runcommand id
684 684 abort: there is no Mercurial repository here (.hg not found)
685 685 [255]
686 686
687 687 >>> from hgclient import check, readchannel, runcommand
688 688 >>> @check
689 689 ... def startwithoutrepo(server):
690 690 ... readchannel(server)
691 691 ... runcommand(server, ['init', 'repo2'])
692 692 ... runcommand(server, ['id', '-R', 'repo2'])
693 693 *** runcommand init repo2
694 694 *** runcommand id -R repo2
695 695 000000000000 tip
696 696
697 697
698 698 don't fall back to cwd if invalid -R path is specified (issue4805):
699 699
700 700 $ cd repo
701 701 $ hg serve --cmdserver pipe -R ../nonexistent
702 702 abort: repository ../nonexistent not found!
703 703 [255]
704 704 $ cd ..
705 705
706 706
707 707 unix domain socket:
708 708
709 709 $ cd repo
710 710 $ hg update -q
711 711
712 712 #if unix-socket unix-permissions
713 713
714 714 >>> from __future__ import print_function
715 715 >>> from hgclient import check, readchannel, runcommand, stringio, unixserver
716 716 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
717 717 >>> def hellomessage(conn):
718 718 ... ch, data = readchannel(conn)
719 719 ... print('%c, %r' % (ch, data))
720 720 ... runcommand(conn, ['id'])
721 721 >>> check(hellomessage, server.connect)
722 722 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
723 723 *** runcommand id
724 724 eff892de26ec tip bm1/bm2/bm3
725 725 >>> def unknowncommand(conn):
726 726 ... readchannel(conn)
727 727 ... conn.stdin.write('unknowncommand\n')
728 728 >>> check(unknowncommand, server.connect) # error sent to server.log
729 729 >>> def serverinput(conn):
730 730 ... readchannel(conn)
731 731 ... patch = """
732 732 ... # HG changeset patch
733 733 ... # User test
734 734 ... # Date 0 0
735 735 ... 2
736 736 ...
737 737 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
738 738 ... --- a/a
739 739 ... +++ b/a
740 740 ... @@ -1,1 +1,2 @@
741 741 ... 1
742 742 ... +2
743 743 ... """
744 744 ... runcommand(conn, ['import', '-'], input=stringio(patch))
745 745 ... runcommand(conn, ['log', '-rtip', '-q'])
746 746 >>> check(serverinput, server.connect)
747 747 *** runcommand import -
748 748 applying patch from stdin
749 749 *** runcommand log -rtip -q
750 750 2:1ed24be7e7a0
751 751 >>> server.shutdown()
752 752
753 753 $ cat .hg/server.log
754 754 listening at .hg/server.sock
755 755 abort: unknown command unknowncommand
756 756 killed!
757 757 $ rm .hg/server.log
758 758
759 759 if server crashed before hello, traceback will be sent to 'e' channel as
760 760 last ditch:
761 761
762 762 $ cat <<EOF >> .hg/hgrc
763 763 > [cmdserver]
764 764 > log = inexistent/path.log
765 765 > EOF
766 766 >>> from __future__ import print_function
767 767 >>> from hgclient import check, readchannel, unixserver
768 768 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
769 769 >>> def earlycrash(conn):
770 770 ... while True:
771 771 ... try:
772 772 ... ch, data = readchannel(conn)
773 773 ... if not data.startswith(' '):
774 774 ... print('%c, %r' % (ch, data))
775 775 ... except EOFError:
776 776 ... break
777 777 >>> check(earlycrash, server.connect)
778 778 e, 'Traceback (most recent call last):\n'
779 779 e, "IOError: *" (glob)
780 780 >>> server.shutdown()
781 781
782 782 $ cat .hg/server.log | grep -v '^ '
783 783 listening at .hg/server.sock
784 784 Traceback (most recent call last):
785 785 IOError: * (glob)
786 786 killed!
787 787 #endif
788 788 #if no-unix-socket
789 789
790 790 $ hg serve --cmdserver unix -a .hg/server.sock
791 791 abort: unsupported platform
792 792 [255]
793 793
794 794 #endif
795 795
796 796 $ cd ..
797 797
798 798 Test that accessing to invalid changelog cache is avoided at
799 799 subsequent operations even if repo object is reused even after failure
800 800 of transaction (see 0a7610758c42 also)
801 801
802 802 "hg log" after failure of transaction is needed to detect invalid
803 803 cache in repoview: this can't detect by "hg verify" only.
804 804
805 805 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
806 806 4) are tested, because '00changelog.i' are differently changed in each
807 807 cases.
808 808
809 809 $ cat > $TESTTMP/failafterfinalize.py <<EOF
810 810 > # extension to abort transaction after finalization forcibly
811 811 > from mercurial import commands, error, extensions, lock as lockmod
812 812 > from mercurial import registrar
813 813 > cmdtable = {}
814 814 > command = registrar.command(cmdtable)
815 815 > configtable = {}
816 816 > configitem = registrar.configitem(configtable)
817 817 > configitem('failafterfinalize', 'fail',
818 818 > default=None,
819 819 > )
820 820 > def fail(tr):
821 821 > raise error.Abort('fail after finalization')
822 822 > def reposetup(ui, repo):
823 823 > class failrepo(repo.__class__):
824 824 > def commitctx(self, ctx, error=False):
825 825 > if self.ui.configbool('failafterfinalize', 'fail'):
826 826 > # 'sorted()' by ASCII code on category names causes
827 827 > # invoking 'fail' after finalization of changelog
828 828 > # using "'cl-%i' % id(self)" as category name
829 829 > self.currenttransaction().addfinalize('zzzzzzzz', fail)
830 830 > return super(failrepo, self).commitctx(ctx, error)
831 831 > repo.__class__ = failrepo
832 832 > EOF
833 833
834 834 $ hg init repo3
835 835 $ cd repo3
836 836
837 837 $ cat <<EOF >> $HGRCPATH
838 838 > [ui]
839 839 > logtemplate = {rev} {desc|firstline} ({files})\n
840 840 >
841 841 > [extensions]
842 842 > failafterfinalize = $TESTTMP/failafterfinalize.py
843 843 > EOF
844 844
845 845 - test failure with "empty changelog"
846 846
847 847 $ echo foo > foo
848 848 $ hg add foo
849 849
850 850 (failure before finalization)
851 851
852 852 >>> from hgclient import check, readchannel, runcommand
853 853 >>> @check
854 854 ... def abort(server):
855 855 ... readchannel(server)
856 856 ... runcommand(server, ['commit',
857 857 ... '--config', 'hooks.pretxncommit=false',
858 858 ... '-mfoo'])
859 859 ... runcommand(server, ['log'])
860 860 ... runcommand(server, ['verify', '-q'])
861 861 *** runcommand commit --config hooks.pretxncommit=false -mfoo
862 862 transaction abort!
863 863 rollback completed
864 864 abort: pretxncommit hook exited with status 1
865 865 [255]
866 866 *** runcommand log
867 867 *** runcommand verify -q
868 868
869 869 (failure after finalization)
870 870
871 871 >>> from hgclient import check, readchannel, runcommand
872 872 >>> @check
873 873 ... def abort(server):
874 874 ... readchannel(server)
875 875 ... runcommand(server, ['commit',
876 876 ... '--config', 'failafterfinalize.fail=true',
877 877 ... '-mfoo'])
878 878 ... runcommand(server, ['log'])
879 879 ... runcommand(server, ['verify', '-q'])
880 880 *** runcommand commit --config failafterfinalize.fail=true -mfoo
881 881 transaction abort!
882 882 rollback completed
883 883 abort: fail after finalization
884 884 [255]
885 885 *** runcommand log
886 886 *** runcommand verify -q
887 887
888 888 - test failure with "not-empty changelog"
889 889
890 890 $ echo bar > bar
891 891 $ hg add bar
892 892 $ hg commit -mbar bar
893 893
894 894 (failure before finalization)
895 895
896 896 >>> from hgclient import check, readchannel, runcommand
897 897 >>> @check
898 898 ... def abort(server):
899 899 ... readchannel(server)
900 900 ... runcommand(server, ['commit',
901 901 ... '--config', 'hooks.pretxncommit=false',
902 902 ... '-mfoo', 'foo'])
903 903 ... runcommand(server, ['log'])
904 904 ... runcommand(server, ['verify', '-q'])
905 905 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
906 906 transaction abort!
907 907 rollback completed
908 908 abort: pretxncommit hook exited with status 1
909 909 [255]
910 910 *** runcommand log
911 911 0 bar (bar)
912 912 *** runcommand verify -q
913 913
914 914 (failure after finalization)
915 915
916 916 >>> from hgclient import check, readchannel, runcommand
917 917 >>> @check
918 918 ... def abort(server):
919 919 ... readchannel(server)
920 920 ... runcommand(server, ['commit',
921 921 ... '--config', 'failafterfinalize.fail=true',
922 922 ... '-mfoo', 'foo'])
923 923 ... runcommand(server, ['log'])
924 924 ... runcommand(server, ['verify', '-q'])
925 925 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
926 926 transaction abort!
927 927 rollback completed
928 928 abort: fail after finalization
929 929 [255]
930 930 *** runcommand log
931 931 0 bar (bar)
932 932 *** runcommand verify -q
933 933
934 934 $ cd ..
935 935
936 936 Test symlink traversal over cached audited paths:
937 937 -------------------------------------------------
938 938
939 939 #if symlink
940 940
941 941 set up symlink hell
942 942
943 943 $ mkdir merge-symlink-out
944 944 $ hg init merge-symlink
945 945 $ cd merge-symlink
946 946 $ touch base
947 947 $ hg commit -qAm base
948 948 $ ln -s ../merge-symlink-out a
949 949 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
950 950 $ hg up -q 0
951 951 $ mkdir a
952 952 $ touch a/poisoned
953 953 $ hg commit -qAm 'file a/poisoned'
954 954 $ hg log -G -T '{rev}: {desc}\n'
955 955 @ 2: file a/poisoned
956 956 |
957 957 | o 1: symlink a -> ../merge-symlink-out
958 958 |/
959 959 o 0: base
960 960
961 961
962 962 try trivial merge after update: cache of audited paths should be discarded,
963 963 and the merge should fail (issue5628)
964 964
965 965 $ hg up -q null
966 966 >>> from hgclient import check, readchannel, runcommand
967 967 >>> @check
968 968 ... def merge(server):
969 969 ... readchannel(server)
970 970 ... # audit a/poisoned as a good path
971 971 ... runcommand(server, ['up', '-qC', '2'])
972 972 ... runcommand(server, ['up', '-qC', '1'])
973 973 ... # here a is a symlink, so a/poisoned is bad
974 974 ... runcommand(server, ['merge', '2'])
975 975 *** runcommand up -qC 2
976 976 *** runcommand up -qC 1
977 977 *** runcommand merge 2
978 a: path conflict - a file or link has the same name as a directory
979 the local file has been renamed to a~aa04623eb0c3
980 resolve manually then use 'hg resolve --mark a'
981 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
982 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
983 [1]
978 abort: path 'a/poisoned' traverses symbolic link 'a'
979 [255]
984 980 $ ls ../merge-symlink-out
985 981
986 982 cache of repo.auditor should be discarded, so matcher would never traverse
987 983 symlinks:
988 984
989 985 $ hg up -qC 0
990 986 $ touch ../merge-symlink-out/poisoned
991 987 >>> from hgclient import check, readchannel, runcommand
992 988 >>> @check
993 989 ... def files(server):
994 990 ... readchannel(server)
995 991 ... runcommand(server, ['up', '-qC', '2'])
996 992 ... # audit a/poisoned as a good path
997 993 ... runcommand(server, ['files', 'a/poisoned'])
998 994 ... runcommand(server, ['up', '-qC', '0'])
999 995 ... runcommand(server, ['up', '-qC', '1'])
1000 996 ... # here 'a' is a symlink, so a/poisoned should be warned
1001 997 ... runcommand(server, ['files', 'a/poisoned'])
1002 998 *** runcommand up -qC 2
1003 999 *** runcommand files a/poisoned
1004 1000 a/poisoned
1005 1001 *** runcommand up -qC 0
1006 1002 *** runcommand up -qC 1
1007 1003 *** runcommand files a/poisoned
1008 1004 abort: path 'a/poisoned' traverses symbolic link 'a'
1009 1005 [255]
1010 1006
1011 1007 $ cd ..
1012 1008
1013 1009 #endif
@@ -1,429 +1,430 b''
1 1 $ cat <<EOF > merge
2 2 > from __future__ import print_function
3 3 > import sys, os
4 4 >
5 5 > try:
6 6 > import msvcrt
7 7 > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
8 8 > msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
9 9 > except ImportError:
10 10 > pass
11 11 >
12 12 > print("merging for", os.path.basename(sys.argv[1]))
13 13 > EOF
14 14 $ HGMERGE="$PYTHON ../merge"; export HGMERGE
15 15
16 16 $ hg init t
17 17 $ cd t
18 18 $ echo This is file a1 > a
19 19 $ hg add a
20 20 $ hg commit -m "commit #0"
21 21 $ echo This is file b1 > b
22 22 $ hg add b
23 23 $ hg commit -m "commit #1"
24 24
25 25 $ hg update 0
26 26 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
27 27
28 28 Test interrupted updates by having a non-empty dir with the same name as one
29 29 of the files in a commit we're updating to
30 30
31 31 $ mkdir b && touch b/nonempty
32 32 $ hg up
33 b: untracked directory conflicts with file
34 abort: untracked files in working directory differ from files in requested revision
35 [255]
33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 34 $ hg ci
37 35 nothing changed
38 36 [1]
39 37 $ hg sum
40 parent: 0:538afb845929
41 commit #0
38 parent: 1:b8bb4a988f25 tip
39 commit #1
42 40 branch: default
43 commit: 1 unknown (clean)
44 update: 1 new changesets (update)
41 commit: (clean)
42 update: (current)
45 43 phases: 2 draft
46 $ rm b/nonempty
44
45 The following line is commented out because the file doesn't exist at the moment, and some OSes error out even with `rm -f`.
46 $ rm b/nonempty
47
47 48 $ hg up
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 50 $ hg sum
50 51 parent: 1:b8bb4a988f25 tip
51 52 commit #1
52 53 branch: default
53 54 commit: (clean)
54 55 update: (current)
55 56 phases: 2 draft
56 57
57 58 Prepare a basic merge
58 59
59 60 $ hg up 0
60 61 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
61 62 $ echo This is file c1 > c
62 63 $ hg add c
63 64 $ hg commit -m "commit #2"
64 65 created new head
65 66 $ echo This is file b1 > b
66 67 no merges expected
67 68 $ hg merge -P 1
68 69 changeset: 1:b8bb4a988f25
69 70 user: test
70 71 date: Thu Jan 01 00:00:00 1970 +0000
71 72 summary: commit #1
72 73
73 74 $ hg merge 1
74 75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 76 (branch merge, don't forget to commit)
76 77 $ hg diff --nodates
77 78 diff -r 49035e18a8e6 b
78 79 --- /dev/null
79 80 +++ b/b
80 81 @@ -0,0 +1,1 @@
81 82 +This is file b1
82 83 $ hg status
83 84 M b
84 85 $ cd ..; rm -r t
85 86
86 87 $ hg init t
87 88 $ cd t
88 89 $ echo This is file a1 > a
89 90 $ hg add a
90 91 $ hg commit -m "commit #0"
91 92 $ echo This is file b1 > b
92 93 $ hg add b
93 94 $ hg commit -m "commit #1"
94 95
95 96 $ hg update 0
96 97 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
97 98 $ echo This is file c1 > c
98 99 $ hg add c
99 100 $ hg commit -m "commit #2"
100 101 created new head
101 102 $ echo This is file b2 > b
102 103 merge should fail
103 104 $ hg merge 1
104 105 b: untracked file differs
105 106 abort: untracked files in working directory differ from files in requested revision
106 107 [255]
107 108
108 109 #if symlink
109 110 symlinks to directories should be treated as regular files (issue5027)
110 111 $ rm b
111 112 $ ln -s 'This is file b2' b
112 113 $ hg merge 1
113 114 b: untracked file differs
114 115 abort: untracked files in working directory differ from files in requested revision
115 116 [255]
116 117 symlinks shouldn't be followed
117 118 $ rm b
118 119 $ echo This is file b1 > .hg/b
119 120 $ ln -s .hg/b b
120 121 $ hg merge 1
121 122 b: untracked file differs
122 123 abort: untracked files in working directory differ from files in requested revision
123 124 [255]
124 125
125 126 $ rm b
126 127 $ echo This is file b2 > b
127 128 #endif
128 129
129 130 bad config
130 131 $ hg merge 1 --config merge.checkunknown=x
131 132 abort: merge.checkunknown not valid ('x' is none of 'abort', 'ignore', 'warn')
132 133 [255]
133 134 this merge should fail
134 135 $ hg merge 1 --config merge.checkunknown=abort
135 136 b: untracked file differs
136 137 abort: untracked files in working directory differ from files in requested revision
137 138 [255]
138 139
139 140 this merge should warn
140 141 $ hg merge 1 --config merge.checkunknown=warn
141 142 b: replacing untracked file
142 143 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 144 (branch merge, don't forget to commit)
144 145 $ cat b.orig
145 146 This is file b2
146 147 $ hg up --clean 2
147 148 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
148 149 $ mv b.orig b
149 150
150 151 this merge should silently ignore
151 152 $ cat b
152 153 This is file b2
153 154 $ hg merge 1 --config merge.checkunknown=ignore
154 155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 156 (branch merge, don't forget to commit)
156 157
157 158 merge.checkignored
158 159 $ hg up --clean 1
159 160 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
160 161 $ cat >> .hgignore << EOF
161 162 > remoteignored
162 163 > EOF
163 164 $ echo This is file localignored3 > localignored
164 165 $ echo This is file remoteignored3 > remoteignored
165 166 $ hg add .hgignore localignored remoteignored
166 167 $ hg commit -m "commit #3"
167 168
168 169 $ hg up 2
169 170 1 files updated, 0 files merged, 4 files removed, 0 files unresolved
170 171 $ cat >> .hgignore << EOF
171 172 > localignored
172 173 > EOF
173 174 $ hg add .hgignore
174 175 $ hg commit -m "commit #4"
175 176
176 177 remote .hgignore shouldn't be used for determining whether a file is ignored
177 178 $ echo This is file remoteignored4 > remoteignored
178 179 $ hg merge 3 --config merge.checkignored=ignore --config merge.checkunknown=abort
179 180 remoteignored: untracked file differs
180 181 abort: untracked files in working directory differ from files in requested revision
181 182 [255]
182 183 $ hg merge 3 --config merge.checkignored=abort --config merge.checkunknown=ignore
183 184 merging .hgignore
184 185 merging for .hgignore
185 186 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
186 187 (branch merge, don't forget to commit)
187 188 $ cat remoteignored
188 189 This is file remoteignored3
189 190 $ cat remoteignored.orig
190 191 This is file remoteignored4
191 192 $ rm remoteignored.orig
192 193
193 194 local .hgignore should be used for that
194 195 $ hg up --clean 4
195 196 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
196 197 $ echo This is file localignored4 > localignored
197 198 also test other conflicting files to see we output the full set of warnings
198 199 $ echo This is file b2 > b
199 200 $ hg merge 3 --config merge.checkignored=abort --config merge.checkunknown=abort
200 201 b: untracked file differs
201 202 localignored: untracked file differs
202 203 abort: untracked files in working directory differ from files in requested revision
203 204 [255]
204 205 $ hg merge 3 --config merge.checkignored=abort --config merge.checkunknown=ignore
205 206 localignored: untracked file differs
206 207 abort: untracked files in working directory differ from files in requested revision
207 208 [255]
208 209 $ hg merge 3 --config merge.checkignored=warn --config merge.checkunknown=abort
209 210 b: untracked file differs
210 211 abort: untracked files in working directory differ from files in requested revision
211 212 [255]
212 213 $ hg merge 3 --config merge.checkignored=warn --config merge.checkunknown=warn
213 214 b: replacing untracked file
214 215 localignored: replacing untracked file
215 216 merging .hgignore
216 217 merging for .hgignore
217 218 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
218 219 (branch merge, don't forget to commit)
219 220 $ cat localignored
220 221 This is file localignored3
221 222 $ cat localignored.orig
222 223 This is file localignored4
223 224 $ rm localignored.orig
224 225
225 226 $ cat b.orig
226 227 This is file b2
227 228 $ hg up --clean 2
228 229 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
229 230 $ mv b.orig b
230 231
231 232 this merge of b should work
232 233 $ cat b
233 234 This is file b2
234 235 $ hg merge -f 1
235 236 merging b
236 237 merging for b
237 238 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
238 239 (branch merge, don't forget to commit)
239 240 $ hg diff --nodates
240 241 diff -r 49035e18a8e6 b
241 242 --- /dev/null
242 243 +++ b/b
243 244 @@ -0,0 +1,1 @@
244 245 +This is file b2
245 246 $ hg status
246 247 M b
247 248 $ cd ..; rm -r t
248 249
249 250 $ hg init t
250 251 $ cd t
251 252 $ echo This is file a1 > a
252 253 $ hg add a
253 254 $ hg commit -m "commit #0"
254 255 $ echo This is file b1 > b
255 256 $ hg add b
256 257 $ hg commit -m "commit #1"
257 258 $ echo This is file b22 > b
258 259 $ hg commit -m "commit #2"
259 260 $ hg update 1
260 261 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 262 $ echo This is file c1 > c
262 263 $ hg add c
263 264 $ hg commit -m "commit #3"
264 265 created new head
265 266
266 267 Contents of b should be "this is file b1"
267 268 $ cat b
268 269 This is file b1
269 270
270 271 $ echo This is file b22 > b
271 272 merge fails
272 273 $ hg merge 2
273 274 abort: uncommitted changes
274 275 (use 'hg status' to list changes)
275 276 [255]
276 277 merge expected!
277 278 $ hg merge -f 2
278 279 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 280 (branch merge, don't forget to commit)
280 281 $ hg diff --nodates
281 282 diff -r 85de557015a8 b
282 283 --- a/b
283 284 +++ b/b
284 285 @@ -1,1 +1,1 @@
285 286 -This is file b1
286 287 +This is file b22
287 288 $ hg status
288 289 M b
289 290 $ cd ..; rm -r t
290 291
291 292 $ hg init t
292 293 $ cd t
293 294 $ echo This is file a1 > a
294 295 $ hg add a
295 296 $ hg commit -m "commit #0"
296 297 $ echo This is file b1 > b
297 298 $ hg add b
298 299 $ hg commit -m "commit #1"
299 300 $ echo This is file b22 > b
300 301 $ hg commit -m "commit #2"
301 302 $ hg update 1
302 303 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
303 304 $ echo This is file c1 > c
304 305 $ hg add c
305 306 $ hg commit -m "commit #3"
306 307 created new head
307 308 $ echo This is file b33 > b
308 309 merge of b should fail
309 310 $ hg merge 2
310 311 abort: uncommitted changes
311 312 (use 'hg status' to list changes)
312 313 [255]
313 314 merge of b expected
314 315 $ hg merge -f 2
315 316 merging b
316 317 merging for b
317 318 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
318 319 (branch merge, don't forget to commit)
319 320 $ hg diff --nodates
320 321 diff -r 85de557015a8 b
321 322 --- a/b
322 323 +++ b/b
323 324 @@ -1,1 +1,1 @@
324 325 -This is file b1
325 326 +This is file b33
326 327 $ hg status
327 328 M b
328 329
329 330 Test for issue2364
330 331
331 332 $ hg up -qC .
332 333 $ hg rm b
333 334 $ hg ci -md
334 335 $ hg revert -r -2 b
335 336 $ hg up -q -- -2
336 337
337 338 Test that updated files are treated as "modified", when
338 339 'merge.update()' is aborted before 'merge.recordupdates()' (= parents
339 340 aren't changed), even if none of mode, size and timestamp of them
340 341 isn't changed on the filesystem (see also issue4583).
341 342
342 343 $ cat > $TESTTMP/abort.py <<EOF
343 344 > from __future__ import absolute_import
344 345 > # emulate aborting before "recordupdates()". in this case, files
345 346 > # are changed without updating dirstate
346 347 > from mercurial import (
347 348 > error,
348 349 > extensions,
349 350 > merge,
350 351 > )
351 352 > def applyupdates(orig, *args, **kwargs):
352 353 > orig(*args, **kwargs)
353 354 > raise error.Abort('intentional aborting')
354 355 > def extsetup(ui):
355 356 > extensions.wrapfunction(merge, "applyupdates", applyupdates)
356 357 > EOF
357 358
358 359 $ cat >> .hg/hgrc <<EOF
359 360 > [fakedirstatewritetime]
360 361 > # emulate invoking dirstate.write() via repo.status()
361 362 > # at 2000-01-01 00:00
362 363 > fakenow = 200001010000
363 364 > EOF
364 365
365 366 (file gotten from other revision)
366 367
367 368 $ hg update -q -C 2
368 369 $ echo 'THIS IS FILE B5' > b
369 370 $ hg commit -m 'commit #5'
370 371
371 372 $ hg update -q -C 3
372 373 $ cat b
373 374 This is file b1
374 375 $ touch -t 200001010000 b
375 376 $ hg debugrebuildstate
376 377
377 378 $ cat >> .hg/hgrc <<EOF
378 379 > [extensions]
379 380 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
380 381 > abort = $TESTTMP/abort.py
381 382 > EOF
382 383 $ hg merge 5
383 384 abort: intentional aborting
384 385 [255]
385 386 $ cat >> .hg/hgrc <<EOF
386 387 > [extensions]
387 388 > fakedirstatewritetime = !
388 389 > abort = !
389 390 > EOF
390 391
391 392 $ cat b
392 393 THIS IS FILE B5
393 394 $ touch -t 200001010000 b
394 395 $ hg status -A b
395 396 M b
396 397
397 398 (file merged from other revision)
398 399
399 400 $ hg update -q -C 3
400 401 $ echo 'this is file b6' > b
401 402 $ hg commit -m 'commit #6'
402 403 created new head
403 404
404 405 $ cat b
405 406 this is file b6
406 407 $ touch -t 200001010000 b
407 408 $ hg debugrebuildstate
408 409
409 410 $ cat >> .hg/hgrc <<EOF
410 411 > [extensions]
411 412 > fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
412 413 > abort = $TESTTMP/abort.py
413 414 > EOF
414 415 $ hg merge --tool internal:other 5
415 416 abort: intentional aborting
416 417 [255]
417 418 $ cat >> .hg/hgrc <<EOF
418 419 > [extensions]
419 420 > fakedirstatewritetime = !
420 421 > abort = !
421 422 > EOF
422 423
423 424 $ cat b
424 425 THIS IS FILE B5
425 426 $ touch -t 200001010000 b
426 427 $ hg status -A b
427 428 M b
428 429
429 430 $ cd ..
@@ -1,99 +1,106 b''
1 Path conflict checking is currently disabled by default because of issue5716.
2 Turn it on for this test.
3
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
6 > merge.checkpathconflicts=True
7 > EOF
8
1 9 $ hg init repo
2 10 $ cd repo
3 11 $ echo base > base
4 12 $ hg add base
5 13 $ hg commit -m "base"
6 14 $ hg bookmark -i base
7 15 $ echo 1 > a
8 16 $ hg add a
9 17 $ hg commit -m "file"
10 18 $ hg bookmark -i file
11 19 $ echo 2 > a
12 20 $ hg commit -m "file2"
13 21 $ hg bookmark -i file2
14 22 $ hg up -q 0
15 23 $ mkdir a
16 24 $ echo 2 > a/b
17 25 $ hg add a/b
18 26 $ hg commit -m "dir"
19 27 created new head
20 28 $ hg bookmark -i dir
21 29
22 30 Basic merge - local file conflicts with remote directory
23 31
24 32 $ hg up -q file
25 33 $ hg bookmark -i
26 34 $ hg merge --verbose dir
27 35 resolving manifests
28 36 a: path conflict - a file or link has the same name as a directory
29 37 the local file has been renamed to a~853701544ac3
30 38 resolve manually then use 'hg resolve --mark a'
31 39 moving a to a~853701544ac3
32 40 getting a/b
33 41 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
34 42 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
35 43 [1]
36 44 $ hg update --clean .
37 45 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 46 $ rm a~853701544ac3
39 47
40 48 Basic update - local directory conflicts with remote file
41 49
42 50 $ hg up -q 0
43 51 $ mkdir a
44 52 $ echo 3 > a/b
45 53 $ hg up file
46 54 a: untracked directory conflicts with file
47 55 abort: untracked files in working directory differ from files in requested revision
48 56 [255]
49 57 $ hg up --clean file
50 58 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 59 (activating bookmark file)
52 60
53 61 Repo state is ok
54 62
55 63 $ hg sum
56 64 parent: 1:853701544ac3
57 65 file
58 66 branch: default
59 67 bookmarks: *file
60 68 commit: (clean)
61 69 update: 2 new changesets (update)
62 70 phases: 4 draft
63 71
64 72 Basic update - untracked file conflicts with remote directory
65 73
66 74 $ hg up -q 0
67 75 $ echo untracked > a
68 76 $ hg up --config merge.checkunknown=warn dir
69 77 a: replacing untracked file
70 78 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 79 (activating bookmark dir)
72 80 $ cat a.orig
73 81 untracked
74 82 $ rm -f a.orig
75 83
76 84 Basic clean update - local directory conflicts with changed remote file
77 85
78 86 $ hg up -q file
79 87 $ rm a
80 88 $ mkdir a
81 89 $ echo 4 > a/b
82 90 $ hg up file2
83 91 abort: *: '$TESTTMP/repo/a' (glob)
84 92 [255]
85 93 $ hg up --clean file2
86 94 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 95 (activating bookmark file2)
88 96
89 97 Repo state is ok
90 98
91 99 $ hg sum
92 100 parent: 2:f64e09fac717
93 101 file2
94 102 branch: default
95 103 bookmarks: *file2
96 104 commit: (clean)
97 105 update: 1 new changesets, 2 branch heads (merge)
98 106 phases: 4 draft
99
@@ -1,128 +1,136 b''
1 Path conflict checking is currently disabled by default because of issue5716.
2 Turn it on for this test.
3
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
6 > merge.checkpathconflicts=True
7 > EOF
8
1 9 $ hg init repo
2 10 $ cd repo
3 11 $ echo base > base
4 12 $ hg add base
5 13 $ hg commit -m "base"
6 14 $ hg bookmark -i base
7 15 $ mkdir a
8 16 $ echo 1 > a/b
9 17 $ hg add a/b
10 18 $ hg commit -m "file"
11 19 $ hg bookmark -i file
12 20 $ echo 2 > a/b
13 21 $ hg commit -m "file2"
14 22 $ hg bookmark -i file2
15 23 $ hg up 0
16 24 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
17 25 $ mkdir a
18 26 $ ln -s c a/b
19 27 $ hg add a/b
20 28 $ hg commit -m "link"
21 29 created new head
22 30 $ hg bookmark -i link
23 31 $ hg up 0
24 32 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
25 33 $ mkdir -p a/b/c
26 34 $ echo 2 > a/b/c/d
27 35 $ hg add a/b/c/d
28 36 $ hg commit -m "dir"
29 37 created new head
30 38 $ hg bookmark -i dir
31 39
32 40 Merge - local file conflicts with remote directory
33 41
34 42 $ hg up file
35 43 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
36 44 (activating bookmark file)
37 45 $ hg bookmark -i
38 46 $ hg merge --verbose dir
39 47 resolving manifests
40 48 a/b: path conflict - a file or link has the same name as a directory
41 49 the local file has been renamed to a/b~0ed027b96f31
42 50 resolve manually then use 'hg resolve --mark a/b'
43 51 moving a/b to a/b~0ed027b96f31 (glob)
44 52 getting a/b/c/d
45 53 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
46 54 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
47 55 [1]
48 56 $ hg status
49 57 M a/b/c/d
50 58 A a/b~0ed027b96f31
51 59 R a/b
52 60 $ hg resolve --all
53 61 a/b: path conflict must be resolved manually
54 62 $ hg forget a/b~0ed027b96f31 && rm a/b~0ed027b96f31
55 63 $ hg resolve --mark a/b
56 64 (no more unresolved files)
57 65 $ hg commit -m "merge file and dir (deleted file)"
58 66
59 67 Merge - local symlink conflicts with remote directory
60 68
61 69 $ hg up link
62 70 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
63 71 (activating bookmark link)
64 72 $ hg bookmark -i
65 73 $ hg merge dir
66 74 a/b: path conflict - a file or link has the same name as a directory
67 75 the local file has been renamed to a/b~2ea68033e3be
68 76 resolve manually then use 'hg resolve --mark a/b'
69 77 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
70 78 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
71 79 [1]
72 80 $ hg status
73 81 M a/b/c/d
74 82 A a/b~2ea68033e3be
75 83 R a/b
76 84 $ hg resolve --list
77 85 P a/b
78 86 $ hg resolve --all
79 87 a/b: path conflict must be resolved manually
80 88 $ hg mv a/b~2ea68033e3be a/b.old
81 89 $ hg resolve --mark a/b
82 90 (no more unresolved files)
83 91 $ hg resolve --list
84 92 R a/b
85 93 $ hg commit -m "merge link and dir (renamed link)"
86 94
87 95 Merge - local directory conflicts with remote file or link
88 96
89 97 $ hg up dir
90 98 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
91 99 (activating bookmark dir)
92 100 $ hg bookmark -i
93 101 $ hg merge file
94 102 a/b: path conflict - a file or link has the same name as a directory
95 103 the remote file has been renamed to a/b~0ed027b96f31
96 104 resolve manually then use 'hg resolve --mark a/b'
97 105 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
98 106 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
99 107 [1]
100 108 $ hg status
101 109 A a/b~0ed027b96f31
102 110 $ hg resolve --all
103 111 a/b: path conflict must be resolved manually
104 112 $ hg mv a/b~0ed027b96f31 a/b/old-b
105 113 $ hg resolve --mark a/b
106 114 (no more unresolved files)
107 115 $ hg commit -m "merge dir and file (move file into dir)"
108 116 created new head
109 117 $ hg merge file2
110 118 merging a/b/old-b and a/b to a/b/old-b
111 119 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
112 120 (branch merge, don't forget to commit)
113 121 $ cat a/b/old-b
114 122 2
115 123 $ hg commit -m "merge file2 (copytrace tracked rename)"
116 124 $ hg merge link
117 125 a/b: path conflict - a file or link has the same name as a directory
118 126 the remote file has been renamed to a/b~2ea68033e3be
119 127 resolve manually then use 'hg resolve --mark a/b'
120 128 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
121 129 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
122 130 [1]
123 131 $ hg mv a/b~2ea68033e3be a/b.old
124 132 $ readlink.py a/b.old
125 133 a/b.old -> c
126 134 $ hg resolve --mark a/b
127 135 (no more unresolved files)
128 136 $ hg commit -m "merge link (rename link)"
@@ -1,153 +1,160 b''
1 Path conflict checking is currently disabled by default because of issue5716.
2 Turn it on for this test.
3
4 $ cat >> $HGRCPATH << EOF
5 > [experimental]
6 > merge.checkpathconflicts=True
7 > EOF
8
1 9 $ hg init repo
2 10 $ cd repo
3 11 $ echo base > base
4 12 $ hg add base
5 13 $ hg commit -m "base"
6 14 $ hg bookmark -i base
7 15 $ mkdir a
8 16 $ echo 1 > a/b
9 17 $ hg add a/b
10 18 $ hg commit -m "file"
11 19 $ hg bookmark -i file
12 20 $ echo 2 > a/b
13 21 $ hg commit -m "file2"
14 22 $ hg bookmark -i file2
15 23 $ hg up 0
16 24 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
17 25 $ mkdir a
18 26 #if symlink
19 27 $ ln -s c a/b
20 28 #else
21 29 $ touch a/b
22 30 #endif
23 31 $ hg add a/b
24 32 $ hg commit -m "link"
25 33 created new head
26 34 $ hg bookmark -i link
27 35 $ hg up 0
28 36 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
29 37 $ mkdir -p a/b/c
30 38 $ echo 2 > a/b/c/d
31 39 $ hg add a/b/c/d
32 40 $ hg commit -m "dir"
33 41 created new head
34 42 $ hg bookmark -i dir
35 43
36 44 Update - local file conflicts with remote directory:
37 45
38 46 $ hg up -q 0
39 47 $ mkdir a
40 48 $ echo 9 > a/b
41 49 $ hg up dir
42 50 a/b: untracked file conflicts with directory
43 51 abort: untracked files in working directory differ from files in requested revision
44 52 [255]
45 53 $ hg up dir --config merge.checkunknown=warn
46 54 a/b: replacing untracked file
47 55 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 56 (activating bookmark dir)
49 57 $ cat a/b.orig
50 58 9
51 59 $ rm a/b.orig
52 60
53 61 Update - local symlink conflicts with remote directory:
54 62
55 63 $ hg up -q 0
56 64 $ mkdir a
57 65 #if symlink
58 66 $ ln -s x a/b
59 67 #else
60 68 $ touch a/b
61 69 #endif
62 70 $ hg up dir
63 71 a/b: untracked file conflicts with directory
64 72 abort: untracked files in working directory differ from files in requested revision
65 73 [255]
66 74 $ hg up dir --config merge.checkunknown=warn
67 75 a/b: replacing untracked file
68 76 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 77 (activating bookmark dir)
70 78 #if symlink
71 79 $ readlink.py a/b.orig
72 80 a/b.orig -> x
73 81 #endif
74 82 $ rm a/b.orig
75 83
76 84 Update - local directory conflicts with remote file
77 85
78 86 $ hg up -q 0
79 87 $ mkdir -p a/b/c
80 88 $ echo 9 > a/b/c/d
81 89 $ hg up file
82 90 a/b: untracked directory conflicts with file
83 91 abort: untracked files in working directory differ from files in requested revision
84 92 [255]
85 93 $ hg up file --config merge.checkunknown=warn
86 94 a/b: replacing untracked files in directory
87 95 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 96 (activating bookmark file)
89 97 $ cat a/b
90 98 1
91 99 $ test -d a/b.orig
92 100 $ rm -rf a/b.orig
93 101
94 102 Update - local directory conflicts with remote symlink
95 103
96 104 $ hg up -q 0
97 105 $ mkdir -p a/b/c
98 106 $ echo 9 > a/b/c/d
99 107 $ hg up link
100 108 a/b: untracked directory conflicts with file
101 109 abort: untracked files in working directory differ from files in requested revision
102 110 [255]
103 111 $ hg up link --config merge.checkunknown=warn
104 112 a/b: replacing untracked files in directory
105 113 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 114 (activating bookmark link)
107 115 #if symlink
108 116 $ readlink.py a/b
109 117 a/b -> c
110 118 #endif
111 119 $ test -d a/b.orig
112 120 $ rm -rf a/b.orig
113 121
114 122 Update - local renamed file conflicts with remote directory
115 123
116 124 $ hg up -q 0
117 125 $ hg mv base a
118 126 $ hg status -C
119 127 A a
120 128 base
121 129 R base
122 130 $ hg up --check dir
123 131 abort: uncommitted changes
124 132 [255]
125 133 $ hg up dir
126 134 a: path conflict - a file or link has the same name as a directory
127 135 the local file has been renamed to a~d20a80d4def3
128 136 resolve manually then use 'hg resolve --mark a'
129 137 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
130 138 use 'hg resolve' to retry unresolved file merges
131 139 (activating bookmark dir)
132 140 [1]
133 141 $ hg status -C
134 142 A a~d20a80d4def3
135 143 base
136 144 R base
137 145 $ hg resolve --list
138 146 P a
139 147 $ hg up --clean -q 0
140 148
141 149 Update clean - local directory conflicts with changed remote file
142 150
143 151 $ hg up -q file
144 152 $ rm a/b
145 153 $ mkdir a/b
146 154 $ echo 9 > a/b/c
147 155 $ hg up file2 --check --config merge.checkunknown=warn
148 156 abort: uncommitted changes
149 157 [255]
150 158 $ hg up file2 --clean
151 159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
152 160 (activating bookmark file2)
153
@@ -1,91 +1,89 b''
1 1 Test update logic when there are renames or weird same-name cases between dirs
2 2 and files
3 3
4 4 Update with local changes across a file rename
5 5
6 6 $ hg init r1 && cd r1
7 7
8 8 $ echo a > a
9 9 $ hg add a
10 10 $ hg ci -m a
11 11
12 12 $ hg mv a b
13 13 $ hg ci -m rename
14 14
15 15 $ echo b > b
16 16 $ hg ci -m change
17 17
18 18 $ hg up -q 0
19 19
20 20 $ echo c > a
21 21
22 22 $ hg up
23 23 merging a and b to b
24 24 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
25 25 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
26 26 use 'hg resolve' to retry unresolved file merges
27 27 [1]
28 28
29 29 Test update when local untracked directory exists with the same name as a
30 30 tracked file in a commit we are updating to
31 31 $ hg init r2 && cd r2
32 32 $ echo root > root && hg ci -Am root # rev 0
33 33 adding root
34 34 $ echo text > name && hg ci -Am "name is a file" # rev 1
35 35 adding name
36 36 $ hg up 0
37 37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 38 $ mkdir name
39 39 $ hg up 1
40 40 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 41
42 42 Test update when local untracked directory exists with some files in it and has
43 43 the same name a tracked file in a commit we are updating to. In future this
44 44 should be updated to give an friendlier error message, but now we should just
45 45 make sure that this does not erase untracked data
46 46 $ hg up 0
47 47 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
48 48 $ mkdir name
49 49 $ echo text > name/file
50 50 $ hg st
51 51 ? name/file
52 52 $ hg up 1
53 name: untracked directory conflicts with file
54 abort: untracked files in working directory differ from files in requested revision
55 [255]
53 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 54 $ cd ..
57 55
58 56 #if symlink
59 57
60 58 Test update when two commits have symlinks that point to different folders
61 59 $ hg init r3 && cd r3
62 60 $ echo root > root && hg ci -Am root
63 61 adding root
64 62 $ mkdir folder1 && mkdir folder2
65 63 $ ln -s folder1 folder
66 64 $ hg ci -Am "symlink to folder1"
67 65 adding folder
68 66 $ rm folder
69 67 $ ln -s folder2 folder
70 68 $ hg ci -Am "symlink to folder2"
71 69 $ hg up 1
72 70 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 71 $ cd ..
74 72
75 73 #endif
76 74
77 75 #if rmcwd
78 76
79 77 Test that warning is printed if cwd is deleted during update
80 78 $ hg init r4 && cd r4
81 79 $ mkdir dir
82 80 $ cd dir
83 81 $ echo a > a
84 82 $ echo b > b
85 83 $ hg add a b
86 84 $ hg ci -m "file and dir"
87 85 $ hg up -q null
88 86 current directory was removed
89 87 (consider changing to repo root: $TESTTMP/r1/r4)
90 88
91 89 #endif
General Comments 0
You need to be logged in to leave comments. Login now