1#require no-rhg no-chg 2 3XXX-RHG this test hangs if `hg` is really `rhg`. This was hidden by the use of 4`alias hg=rhg` by run-tests.py. With such alias removed, this test is revealed 5buggy. This need to be resolved sooner than later. 6 7XXX-CHG this test hangs if `hg` is really `chg`. This was hidden by the use of 8`alias hg=chg` by run-tests.py. With such alias removed, this test is revealed 9buggy. This need to be resolved sooner than later. 10 11#if windows 12 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH" 13#else 14 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH" 15#endif 16 $ export PYTHONPATH 17 18typical client does not want echo-back messages, so test without it: 19 20 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new 21 $ mv $HGRCPATH.new $HGRCPATH 22 23 $ hg init repo 24 $ cd repo 25 26 >>> from __future__ import absolute_import 27 >>> import os 28 >>> import sys 29 >>> from hgclient import bprint, check, readchannel, runcommand 30 >>> @check 31 ... def hellomessage(server): 32 ... ch, data = readchannel(server) 33 ... bprint(b'%c, %r' % (ch, data)) 34 ... # run an arbitrary command to make sure the next thing the server 35 ... # sends isn't part of the hello message 36 ... runcommand(server, [b'id']) 37 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) 38 *** runcommand id 39 000000000000 tip 40 41 >>> from hgclient import check 42 >>> @check 43 ... def unknowncommand(server): 44 ... server.stdin.write(b'unknowncommand\n') 45 abort: unknown command unknowncommand 46 47 >>> from hgclient import check, readchannel, runcommand 48 >>> @check 49 ... def checkruncommand(server): 50 ... # hello block 51 ... readchannel(server) 52 ... 53 ... # no args 54 ... runcommand(server, []) 55 ... 56 ... # global options 57 ... runcommand(server, [b'id', b'--quiet']) 58 ... 59 ... # make sure global options don't stick through requests 60 ... runcommand(server, [b'id']) 61 ... 62 ... # --config 63 ... runcommand(server, [b'id', b'--config', b'ui.quiet=True']) 64 ... 65 ... # make sure --config doesn't stick 66 ... runcommand(server, [b'id']) 67 ... 68 ... # negative return code should be masked 69 ... runcommand(server, [b'id', b'-runknown']) 70 *** runcommand 71 Mercurial Distributed SCM 72 73 basic commands: 74 75 add add the specified files on the next commit 76 annotate show changeset information by line for each file 77 clone make a copy of an existing repository 78 commit commit the specified files or all outstanding changes 79 diff diff repository (or selected files) 80 export dump the header and diffs for one or more changesets 81 forget forget the specified files on the next commit 82 init create a new repository in the given directory 83 log show revision history of entire repository or files 84 merge merge another revision into working directory 85 pull pull changes from the specified source 86 push push changes to the specified destination 87 remove remove the specified files on the next commit 88 serve start stand-alone webserver 89 status show changed files in the working directory 90 summary summarize working directory state 91 update update working directory (or switch revisions) 92 93 (use 'hg help' for the full list of commands or 'hg -v' for details) 94 *** runcommand id --quiet 95 000000000000 96 *** runcommand id 97 000000000000 tip 98 *** runcommand id --config ui.quiet=True 99 000000000000 100 *** runcommand id 101 000000000000 tip 102 *** runcommand id -runknown 103 abort: unknown revision 'unknown' 104 [10] 105 106 >>> from hgclient import bprint, check, readchannel 107 >>> @check 108 ... def inputeof(server): 109 ... readchannel(server) 110 ... server.stdin.write(b'runcommand\n') 111 ... # close stdin while server is waiting for input 112 ... server.stdin.close() 113 ... 114 ... # server exits with 1 if the pipe closed while reading the command 115 ... bprint(b'server exit code =', b'%d' % server.wait()) 116 server exit code = 1 117 118 >>> from hgclient import check, readchannel, runcommand, stringio 119 >>> @check 120 ... def serverinput(server): 121 ... readchannel(server) 122 ... 123 ... patch = b""" 124 ... # HG changeset patch 125 ... # User test 126 ... # Date 0 0 127 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857 128 ... # Parent 0000000000000000000000000000000000000000 129 ... 1 130 ... 131 ... diff -r 000000000000 -r c103a3dec114 a 132 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000 133 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000 134 ... @@ -0,0 +1,1 @@ 135 ... +1 136 ... """ 137 ... 138 ... runcommand(server, [b'import', b'-'], input=stringio(patch)) 139 ... runcommand(server, [b'log']) 140 *** runcommand import - 141 applying patch from stdin 142 *** runcommand log 143 changeset: 0:eff892de26ec 144 tag: tip 145 user: test 146 date: Thu Jan 01 00:00:00 1970 +0000 147 summary: 1 148 149 150check strict parsing of early options: 151 152 >>> import os 153 >>> from hgclient import check, readchannel, runcommand 154 >>> os.environ['HGPLAIN'] = '+strictflags' 155 >>> @check 156 ... def cwd(server): 157 ... readchannel(server) 158 ... runcommand(server, [b'log', b'-b', b'--config=alias.log=!echo pwned', 159 ... b'default']) 160 *** runcommand log -b --config=alias.log=!echo pwned default 161 abort: unknown revision '--config=alias.log=!echo pwned' 162 [255] 163 164check that "histedit --commands=-" can read rules from the input channel: 165 166 >>> from hgclient import check, readchannel, runcommand, stringio 167 >>> @check 168 ... def serverinput(server): 169 ... readchannel(server) 170 ... rules = b'pick eff892de26ec\n' 171 ... runcommand(server, [b'histedit', b'0', b'--commands=-', 172 ... b'--config', b'extensions.histedit='], 173 ... input=stringio(rules)) 174 *** runcommand histedit 0 --commands=- --config extensions.histedit= 175 176check that --cwd doesn't persist between requests: 177 178 $ mkdir foo 179 $ touch foo/bar 180 >>> from hgclient import check, readchannel, runcommand 181 >>> @check 182 ... def cwd(server): 183 ... readchannel(server) 184 ... runcommand(server, [b'--cwd', b'foo', b'st', b'bar']) 185 ... runcommand(server, [b'st', b'foo/bar']) 186 *** runcommand --cwd foo st bar 187 ? bar 188 *** runcommand st foo/bar 189 ? foo/bar 190 191 $ rm foo/bar 192 193 194check that local configs for the cached repo aren't inherited when -R is used: 195 196 $ cat <<EOF >> .hg/hgrc 197 > [ui] 198 > foo = bar 199 > EOF 200 201#if no-extraextensions 202 203 >>> from hgclient import check, readchannel, runcommand, sep 204 >>> @check 205 ... def localhgrc(server): 206 ... readchannel(server) 207 ... 208 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should 209 ... # show it 210 ... runcommand(server, [b'showconfig'], outfilter=sep) 211 ... 212 ... # but not for this repo 213 ... runcommand(server, [b'init', b'foo']) 214 ... runcommand(server, [b'-R', b'foo', b'showconfig', b'ui', b'defaults']) 215 *** runcommand showconfig 216 bundle.mainreporoot=$TESTTMP/repo 217 chgserver.idletimeout=60 218 devel.all-warnings=true 219 devel.default-date=0 0 220 extensions.fsmonitor= (fsmonitor !) 221 format.exp-rc-dirstate-v2=1 (dirstate-v2 !) 222 largefiles.usercache=$TESTTMP/.cache/largefiles 223 lfs.usercache=$TESTTMP/.cache/lfs 224 ui.slash=True 225 ui.interactive=False 226 ui.detailed-exit-code=True 227 ui.merge=internal:merge 228 ui.mergemarkers=detailed 229 ui.ssh=* (glob) 230 ui.timeout.warn=15 231 ui.foo=bar 232 ui.nontty=true 233 web.address=localhost 234 web\.ipv6=(?:True|False) (re) 235 web.server-header=testing stub value 236 *** runcommand init foo 237 *** runcommand -R foo showconfig ui defaults 238 ui.slash=True 239 ui.interactive=False 240 ui.detailed-exit-code=True 241 ui.merge=internal:merge 242 ui.mergemarkers=detailed 243 ui.ssh=* (glob) 244 ui.timeout.warn=15 245 ui.nontty=true 246#endif 247 248 $ rm -R foo 249 250#if windows 251 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH" 252#else 253 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH" 254#endif 255 256 $ cat <<EOF > hook.py 257 > import sys 258 > from hgclient import bprint 259 > def hook(**args): 260 > bprint(b'hook talking') 261 > bprint(b'now try to read something: %r' % sys.stdin.read()) 262 > EOF 263 264 >>> from hgclient import check, readchannel, runcommand, stringio 265 >>> @check 266 ... def hookoutput(server): 267 ... readchannel(server) 268 ... runcommand(server, [b'--config', 269 ... b'hooks.pre-identify=python:hook.hook', 270 ... b'id'], 271 ... input=stringio(b'some input')) 272 *** runcommand --config hooks.pre-identify=python:hook.hook id 273 eff892de26ec tip 274 hook talking 275 now try to read something: '' 276 277Clean hook cached version 278 $ rm hook.py* 279 $ rm -Rf __pycache__ 280 281 $ echo a >> a 282 >>> import os 283 >>> from hgclient import check, readchannel, runcommand 284 >>> @check 285 ... def outsidechanges(server): 286 ... readchannel(server) 287 ... runcommand(server, [b'status']) 288 ... os.system('hg ci -Am2') 289 ... runcommand(server, [b'tip']) 290 ... runcommand(server, [b'status']) 291 *** runcommand status 292 M a 293 *** runcommand tip 294 changeset: 1:d3a0a68be6de 295 tag: tip 296 user: test 297 date: Thu Jan 01 00:00:00 1970 +0000 298 summary: 2 299 300 *** runcommand status 301 302 >>> import os 303 >>> from hgclient import bprint, check, readchannel, runcommand 304 >>> @check 305 ... def bookmarks(server): 306 ... readchannel(server) 307 ... runcommand(server, [b'bookmarks']) 308 ... 309 ... # changes .hg/bookmarks 310 ... os.system('hg bookmark -i bm1') 311 ... os.system('hg bookmark -i bm2') 312 ... runcommand(server, [b'bookmarks']) 313 ... 314 ... # changes .hg/bookmarks.current 315 ... os.system('hg upd bm1 -q') 316 ... runcommand(server, [b'bookmarks']) 317 ... 318 ... runcommand(server, [b'bookmarks', b'bm3']) 319 ... f = open('a', 'ab') 320 ... f.write(b'a\n') and None 321 ... f.close() 322 ... runcommand(server, [b'commit', b'-Amm']) 323 ... runcommand(server, [b'bookmarks']) 324 ... bprint(b'') 325 *** runcommand bookmarks 326 no bookmarks set 327 *** runcommand bookmarks 328 bm1 1:d3a0a68be6de 329 bm2 1:d3a0a68be6de 330 *** runcommand bookmarks 331 * bm1 1:d3a0a68be6de 332 bm2 1:d3a0a68be6de 333 *** runcommand bookmarks bm3 334 *** runcommand commit -Amm 335 *** runcommand bookmarks 336 bm1 1:d3a0a68be6de 337 bm2 1:d3a0a68be6de 338 * bm3 2:aef17e88f5f0 339 340 341 >>> import os 342 >>> from hgclient import check, readchannel, runcommand 343 >>> @check 344 ... def tagscache(server): 345 ... readchannel(server) 346 ... runcommand(server, [b'id', b'-t', b'-r', b'0']) 347 ... os.system('hg tag -r 0 foo') 348 ... runcommand(server, [b'id', b'-t', b'-r', b'0']) 349 *** runcommand id -t -r 0 350 351 *** runcommand id -t -r 0 352 foo 353 354 >>> import os 355 >>> from hgclient import check, readchannel, runcommand 356 >>> @check 357 ... def setphase(server): 358 ... readchannel(server) 359 ... runcommand(server, [b'phase', b'-r', b'.']) 360 ... os.system('hg phase -r . -p') 361 ... runcommand(server, [b'phase', b'-r', b'.']) 362 *** runcommand phase -r . 363 3: draft 364 *** runcommand phase -r . 365 3: public 366 367 $ echo a >> a 368 >>> from hgclient import bprint, check, readchannel, runcommand 369 >>> @check 370 ... def rollback(server): 371 ... readchannel(server) 372 ... runcommand(server, [b'phase', b'-r', b'.', b'-p']) 373 ... runcommand(server, [b'commit', b'-Am.']) 374 ... runcommand(server, [b'rollback']) 375 ... runcommand(server, [b'phase', b'-r', b'.']) 376 ... bprint(b'') 377 *** runcommand phase -r . -p 378 no phases changed 379 *** runcommand commit -Am. 380 *** runcommand rollback 381 repository tip rolled back to revision 3 (undo commit) 382 working directory now based on revision 3 383 *** runcommand phase -r . 384 3: public 385 386 387 >>> import os 388 >>> from hgclient import check, readchannel, runcommand 389 >>> @check 390 ... def branch(server): 391 ... readchannel(server) 392 ... runcommand(server, [b'branch']) 393 ... os.system('hg branch foo') 394 ... runcommand(server, [b'branch']) 395 ... os.system('hg branch default') 396 *** runcommand branch 397 default 398 marked working directory as branch foo 399 (branches are permanent and global, did you want a bookmark?) 400 *** runcommand branch 401 foo 402 marked working directory as branch default 403 (branches are permanent and global, did you want a bookmark?) 404 405 $ touch .hgignore 406 >>> import os 407 >>> from hgclient import bprint, check, readchannel, runcommand 408 >>> @check 409 ... def hgignore(server): 410 ... readchannel(server) 411 ... runcommand(server, [b'commit', b'-Am.']) 412 ... f = open('ignored-file', 'ab') 413 ... f.write(b'') and None 414 ... f.close() 415 ... f = open('.hgignore', 'ab') 416 ... f.write(b'ignored-file') 417 ... f.close() 418 ... runcommand(server, [b'status', b'-i', b'-u']) 419 ... bprint(b'') 420 *** runcommand commit -Am. 421 adding .hgignore 422 *** runcommand status -i -u 423 I ignored-file 424 425 426cache of non-public revisions should be invalidated on repository change 427(issue4855): 428 429 >>> import os 430 >>> from hgclient import bprint, check, readchannel, runcommand 431 >>> @check 432 ... def phasesetscacheaftercommit(server): 433 ... readchannel(server) 434 ... # load _phasecache._phaserevs and _phasesets 435 ... runcommand(server, [b'log', b'-qr', b'draft()']) 436 ... # create draft commits by another process 437 ... for i in range(5, 7): 438 ... f = open('a', 'ab') 439 ... f.seek(0, os.SEEK_END) 440 ... f.write(b'a\n') and None 441 ... f.close() 442 ... os.system('hg commit -Aqm%d' % i) 443 ... # new commits should be listed as draft revisions 444 ... runcommand(server, [b'log', b'-qr', b'draft()']) 445 ... bprint(b'') 446 *** runcommand log -qr draft() 447 4:7966c8e3734d 448 *** runcommand log -qr draft() 449 4:7966c8e3734d 450 5:41f6602d1c4f 451 6:10501e202c35 452 453 454 >>> import os 455 >>> from hgclient import bprint, check, readchannel, runcommand 456 >>> @check 457 ... def phasesetscacheafterstrip(server): 458 ... readchannel(server) 459 ... # load _phasecache._phaserevs and _phasesets 460 ... runcommand(server, [b'log', b'-qr', b'draft()']) 461 ... # strip cached revisions by another process 462 ... os.system('hg --config extensions.strip= strip -q 5') 463 ... # shouldn't abort by "unknown revision '6'" 464 ... runcommand(server, [b'log', b'-qr', b'draft()']) 465 ... bprint(b'') 466 *** runcommand log -qr draft() 467 4:7966c8e3734d 468 5:41f6602d1c4f 469 6:10501e202c35 470 *** runcommand log -qr draft() 471 4:7966c8e3734d 472 473 474cache of phase roots should be invalidated on strip (issue3827): 475 476 >>> import os 477 >>> from hgclient import check, readchannel, runcommand, sep 478 >>> @check 479 ... def phasecacheafterstrip(server): 480 ... readchannel(server) 481 ... 482 ... # create new head, 5:731265503d86 483 ... runcommand(server, [b'update', b'-C', b'0']) 484 ... f = open('a', 'ab') 485 ... f.write(b'a\n') and None 486 ... f.close() 487 ... runcommand(server, [b'commit', b'-Am.', b'a']) 488 ... runcommand(server, [b'log', b'-Gq']) 489 ... 490 ... # make it public; draft marker moves to 4:7966c8e3734d 491 ... runcommand(server, [b'phase', b'-p', b'.']) 492 ... # load _phasecache.phaseroots 493 ... runcommand(server, [b'phase', b'.'], outfilter=sep) 494 ... 495 ... # strip 1::4 outside server 496 ... os.system('hg -q --config extensions.mq= strip 1') 497 ... 498 ... # shouldn't raise "7966c8e3734d: no node!" 499 ... runcommand(server, [b'branches']) 500 *** runcommand update -C 0 501 1 files updated, 0 files merged, 2 files removed, 0 files unresolved 502 (leaving bookmark bm3) 503 *** runcommand commit -Am. a 504 created new head 505 *** runcommand log -Gq 506 @ 5:731265503d86 507 | 508 | o 4:7966c8e3734d 509 | | 510 | o 3:b9b85890c400 511 | | 512 | o 2:aef17e88f5f0 513 | | 514 | o 1:d3a0a68be6de 515 |/ 516 o 0:eff892de26ec 517 518 *** runcommand phase -p . 519 *** runcommand phase . 520 5: public 521 *** runcommand branches 522 default 1:731265503d86 523 524in-memory cache must be reloaded if transaction is aborted. otherwise 525changelog and manifest would have invalid node: 526 527 $ echo a >> a 528 >>> from hgclient import check, readchannel, runcommand 529 >>> @check 530 ... def txabort(server): 531 ... readchannel(server) 532 ... runcommand(server, [b'commit', b'--config', b'hooks.pretxncommit=false', 533 ... b'-mfoo']) 534 ... runcommand(server, [b'verify']) 535 *** runcommand commit --config hooks.pretxncommit=false -mfoo 536 transaction abort! 537 rollback completed 538 abort: pretxncommit hook exited with status 1 539 [40] 540 *** runcommand verify 541 checking changesets 542 checking manifests 543 crosschecking files in changesets and manifests 544 checking files 545 checked 2 changesets with 2 changes to 1 files 546 $ hg revert --no-backup -aq 547 548 $ cat >> .hg/hgrc << EOF 549 > [experimental] 550 > evolution.createmarkers=True 551 > EOF 552 553 >>> import os 554 >>> from hgclient import check, readchannel, runcommand 555 >>> @check 556 ... def obsolete(server): 557 ... readchannel(server) 558 ... 559 ... runcommand(server, [b'up', b'null']) 560 ... runcommand(server, [b'phase', b'-df', b'tip']) 561 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`' 562 ... if os.name == 'nt': 563 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe 564 ... os.system(cmd) 565 ... runcommand(server, [b'log', b'--hidden']) 566 ... runcommand(server, [b'log']) 567 *** runcommand up null 568 0 files updated, 0 files merged, 1 files removed, 0 files unresolved 569 *** runcommand phase -df tip 570 1 new obsolescence markers 571 obsoleted 1 changesets 572 *** runcommand log --hidden 573 changeset: 1:731265503d86 574 tag: tip 575 user: test 576 date: Thu Jan 01 00:00:00 1970 +0000 577 obsolete: pruned 578 summary: . 579 580 changeset: 0:eff892de26ec 581 bookmark: bm1 582 bookmark: bm2 583 bookmark: bm3 584 user: test 585 date: Thu Jan 01 00:00:00 1970 +0000 586 summary: 1 587 588 *** runcommand log 589 changeset: 0:eff892de26ec 590 bookmark: bm1 591 bookmark: bm2 592 bookmark: bm3 593 tag: tip 594 user: test 595 date: Thu Jan 01 00:00:00 1970 +0000 596 summary: 1 597 598 599 $ cat <<EOF >> .hg/hgrc 600 > [extensions] 601 > mq = 602 > EOF 603 604 >>> import os 605 >>> from hgclient import check, readchannel, runcommand 606 >>> @check 607 ... def mqoutsidechanges(server): 608 ... readchannel(server) 609 ... 610 ... # load repo.mq 611 ... runcommand(server, [b'qapplied']) 612 ... os.system('hg qnew 0.diff') 613 ... # repo.mq should be invalidated 614 ... runcommand(server, [b'qapplied']) 615 ... 616 ... runcommand(server, [b'qpop', b'--all']) 617 ... os.system('hg qqueue --create foo') 618 ... # repo.mq should be recreated to point to new queue 619 ... runcommand(server, [b'qqueue', b'--active']) 620 *** runcommand qapplied 621 *** runcommand qapplied 622 0.diff 623 *** runcommand qpop --all 624 popping 0.diff 625 patch queue now empty 626 *** runcommand qqueue --active 627 foo 628 629 $ cat <<'EOF' > ../dbgui.py 630 > import os 631 > import sys 632 > from mercurial import commands, registrar 633 > cmdtable = {} 634 > command = registrar.command(cmdtable) 635 > @command(b"debuggetpass", norepo=True) 636 > def debuggetpass(ui): 637 > ui.write(b"%s\n" % ui.getpass()) 638 > @command(b"debugprompt", norepo=True) 639 > def debugprompt(ui): 640 > ui.write(b"%s\n" % ui.prompt(b"prompt:")) 641 > @command(b"debugpromptchoice", norepo=True) 642 > def debugpromptchoice(ui): 643 > msg = b"promptchoice (y/n)? $$ &Yes $$ &No" 644 > ui.write(b"%d\n" % ui.promptchoice(msg)) 645 > @command(b"debugreadstdin", norepo=True) 646 > def debugreadstdin(ui): 647 > ui.write(b"read: %r\n" % sys.stdin.read(1)) 648 > @command(b"debugwritestdout", norepo=True) 649 > def debugwritestdout(ui): 650 > os.write(1, b"low-level stdout fd and\n") 651 > sys.stdout.write("stdout should be redirected to stderr\n") 652 > sys.stdout.flush() 653 > EOF 654 $ cat <<EOF >> .hg/hgrc 655 > [extensions] 656 > dbgui = ../dbgui.py 657 > EOF 658 659 >>> from hgclient import check, readchannel, runcommand, stringio 660 >>> @check 661 ... def getpass(server): 662 ... readchannel(server) 663 ... runcommand(server, [b'debuggetpass', b'--config', 664 ... b'ui.interactive=True'], 665 ... input=stringio(b'1234\n')) 666 ... runcommand(server, [b'debuggetpass', b'--config', 667 ... b'ui.interactive=True'], 668 ... input=stringio(b'\n')) 669 ... runcommand(server, [b'debuggetpass', b'--config', 670 ... b'ui.interactive=True'], 671 ... input=stringio(b'')) 672 ... runcommand(server, [b'debugprompt', b'--config', 673 ... b'ui.interactive=True'], 674 ... input=stringio(b'5678\n')) 675 ... runcommand(server, [b'debugprompt', b'--config', 676 ... b'ui.interactive=True'], 677 ... input=stringio(b'\nremainder\nshould\nnot\nbe\nread\n')) 678 ... runcommand(server, [b'debugreadstdin']) 679 ... runcommand(server, [b'debugwritestdout']) 680 *** runcommand debuggetpass --config ui.interactive=True 681 password: 1234 682 *** runcommand debuggetpass --config ui.interactive=True 683 password: 684 *** runcommand debuggetpass --config ui.interactive=True 685 password: abort: response expected 686 [255] 687 *** runcommand debugprompt --config ui.interactive=True 688 prompt: 5678 689 *** runcommand debugprompt --config ui.interactive=True 690 prompt: y 691 *** runcommand debugreadstdin 692 read: '' 693 *** runcommand debugwritestdout 694 low-level stdout fd and 695 stdout should be redirected to stderr 696 697 698run commandserver in commandserver, which is silly but should work: 699 700 >>> from hgclient import bprint, check, readchannel, runcommand, stringio 701 >>> @check 702 ... def nested(server): 703 ... bprint(b'%c, %r' % readchannel(server)) 704 ... class nestedserver(object): 705 ... stdin = stringio(b'getencoding\n') 706 ... stdout = stringio() 707 ... runcommand(server, [b'serve', b'--cmdserver', b'pipe'], 708 ... output=nestedserver.stdout, input=nestedserver.stdin) 709 ... nestedserver.stdout.seek(0) 710 ... bprint(b'%c, %r' % readchannel(nestedserver)) # hello 711 ... bprint(b'%c, %r' % readchannel(nestedserver)) # getencoding 712 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) 713 *** runcommand serve --cmdserver pipe 714 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) 715 r, '*' (glob) 716 717 718start without repository: 719 720 $ cd .. 721 722 >>> from hgclient import bprint, check, readchannel, runcommand 723 >>> @check 724 ... def hellomessage(server): 725 ... ch, data = readchannel(server) 726 ... bprint(b'%c, %r' % (ch, data)) 727 ... # run an arbitrary command to make sure the next thing the server 728 ... # sends isn't part of the hello message 729 ... runcommand(server, [b'id']) 730 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) 731 *** runcommand id 732 abort: there is no Mercurial repository here (.hg not found) 733 [10] 734 735 >>> from hgclient import check, readchannel, runcommand 736 >>> @check 737 ... def startwithoutrepo(server): 738 ... readchannel(server) 739 ... runcommand(server, [b'init', b'repo2']) 740 ... runcommand(server, [b'id', b'-R', b'repo2']) 741 *** runcommand init repo2 742 *** runcommand id -R repo2 743 000000000000 tip 744 745 746don't fall back to cwd if invalid -R path is specified (issue4805): 747 748 $ cd repo 749 $ hg serve --cmdserver pipe -R ../nonexistent 750 abort: repository ../nonexistent not found 751 [255] 752 $ cd .. 753 754 755#if no-windows 756 757option to not shutdown on SIGINT: 758 759 $ cat <<'EOF' > dbgint.py 760 > import os 761 > import signal 762 > import time 763 > from mercurial import commands, registrar 764 > cmdtable = {} 765 > command = registrar.command(cmdtable) 766 > @command(b"debugsleep", norepo=True) 767 > def debugsleep(ui): 768 > time.sleep(1) 769 > @command(b"debugsuicide", norepo=True) 770 > def debugsuicide(ui): 771 > os.kill(os.getpid(), signal.SIGINT) 772 > time.sleep(1) 773 > EOF 774 775 >>> import signal 776 >>> import time 777 >>> from hgclient import checkwith, readchannel, runcommand 778 >>> @checkwith(extraargs=[b'--config', b'cmdserver.shutdown-on-interrupt=False', 779 ... b'--config', b'extensions.dbgint=dbgint.py']) 780 ... def nointr(server): 781 ... readchannel(server) 782 ... server.send_signal(signal.SIGINT) # server won't be terminated 783 ... time.sleep(1) 784 ... runcommand(server, [b'debugsleep']) 785 ... server.send_signal(signal.SIGINT) # server won't be terminated 786 ... runcommand(server, [b'debugsleep']) 787 ... runcommand(server, [b'debugsuicide']) # command can be interrupted 788 ... server.send_signal(signal.SIGTERM) # server will be terminated 789 ... time.sleep(1) 790 *** runcommand debugsleep 791 *** runcommand debugsleep 792 *** runcommand debugsuicide 793 interrupted! 794 killed! 795 [255] 796 797#endif 798 799 800structured message channel: 801 802 $ cat <<'EOF' >> repo2/.hg/hgrc 803 > [ui] 804 > # server --config should precede repository option 805 > message-output = stdio 806 > EOF 807 808 >>> from hgclient import bprint, checkwith, readchannel, runcommand 809 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel', 810 ... b'--config', b'cmdserver.message-encodings=foo cbor']) 811 ... def verify(server): 812 ... _ch, data = readchannel(server) 813 ... bprint(data) 814 ... runcommand(server, [b'-R', b'repo2', b'verify']) 815 capabilities: getencoding runcommand 816 encoding: ascii 817 message-encoding: cbor 818 pid: * (glob) 819 pgid: * (glob) (no-windows !) 820 *** runcommand -R repo2 verify 821 message: '\xa2DdataTchecking changesets\nDtypeFstatus' 822 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@' 823 message: '\xa2DdataSchecking manifests\nDtypeFstatus' 824 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@' 825 message: '\xa2DdataX0crosschecking files in changesets and manifests\nDtypeFstatus' 826 message: '\xa6Ditem@Cpos\xf6EtopicMcrosscheckingEtotal\xf6DtypeHprogressDunit@' 827 message: '\xa2DdataOchecking files\nDtypeFstatus' 828 message: '\xa6Ditem@Cpos\xf6EtopicHcheckingEtotal\xf6DtypeHprogressDunit@' 829 message: '\xa2DdataX/checked 0 changesets with 0 changes to 0 files\nDtypeFstatus' 830 831 >>> from hgclient import checkwith, readchannel, runcommand, stringio 832 >>> @checkwith(extraargs=[b'--config', b'ui.message-output=channel', 833 ... b'--config', b'cmdserver.message-encodings=cbor', 834 ... b'--config', b'extensions.dbgui=dbgui.py']) 835 ... def prompt(server): 836 ... readchannel(server) 837 ... interactive = [b'--config', b'ui.interactive=True'] 838 ... runcommand(server, [b'debuggetpass'] + interactive, 839 ... input=stringio(b'1234\n')) 840 ... runcommand(server, [b'debugprompt'] + interactive, 841 ... input=stringio(b'5678\n')) 842 ... runcommand(server, [b'debugpromptchoice'] + interactive, 843 ... input=stringio(b'n\n')) 844 *** runcommand debuggetpass --config ui.interactive=True 845 message: '\xa3DdataJpassword: Hpassword\xf5DtypeFprompt' 846 1234 847 *** runcommand debugprompt --config ui.interactive=True 848 message: '\xa3DdataGprompt:GdefaultAyDtypeFprompt' 849 5678 850 *** runcommand debugpromptchoice --config ui.interactive=True 851 message: '\xa4Gchoices\x82\x82AyCYes\x82AnBNoDdataTpromptchoice (y/n)? GdefaultAyDtypeFprompt' 852 1 853 854bad message encoding: 855 856 $ hg serve --cmdserver pipe --config ui.message-output=channel 857 abort: no supported message encodings: 858 [255] 859 $ hg serve --cmdserver pipe --config ui.message-output=channel \ 860 > --config cmdserver.message-encodings='foo bar' 861 abort: no supported message encodings: foo bar 862 [255] 863 864unix domain socket: 865 866 $ cd repo 867 $ hg update -q 868 869#if unix-socket unix-permissions 870 871 >>> from hgclient import bprint, check, readchannel, runcommand, stringio, unixserver 872 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log') 873 >>> def hellomessage(conn): 874 ... ch, data = readchannel(conn) 875 ... bprint(b'%c, %r' % (ch, data)) 876 ... runcommand(conn, [b'id']) 877 >>> check(hellomessage, server.connect) 878 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob) 879 *** runcommand id 880 eff892de26ec tip bm1/bm2/bm3 881 >>> def unknowncommand(conn): 882 ... readchannel(conn) 883 ... conn.stdin.write(b'unknowncommand\n') 884 >>> check(unknowncommand, server.connect) # error sent to server.log 885 >>> def serverinput(conn): 886 ... readchannel(conn) 887 ... patch = b""" 888 ... # HG changeset patch 889 ... # User test 890 ... # Date 0 0 891 ... 2 892 ... 893 ... diff -r eff892de26ec -r 1ed24be7e7a0 a 894 ... --- a/a 895 ... +++ b/a 896 ... @@ -1,1 +1,2 @@ 897 ... 1 898 ... +2 899 ... """ 900 ... runcommand(conn, [b'import', b'-'], input=stringio(patch)) 901 ... runcommand(conn, [b'log', b'-rtip', b'-q']) 902 >>> check(serverinput, server.connect) 903 *** runcommand import - 904 applying patch from stdin 905 *** runcommand log -rtip -q 906 2:1ed24be7e7a0 907 >>> server.shutdown() 908 909 $ cat .hg/server.log 910 listening at .hg/server.sock 911 abort: unknown command unknowncommand 912 killed! 913 $ rm .hg/server.log 914 915 if server crashed before hello, traceback will be sent to 'e' channel as 916 last ditch: 917 918 $ cat <<'EOF' > ../earlycrasher.py 919 > from mercurial import commandserver, extensions 920 > def _serverequest(orig, ui, repo, conn, createcmdserver, prereposetups): 921 > def createcmdserver(*args, **kwargs): 922 > raise Exception('crash') 923 > return orig(ui, repo, conn, createcmdserver, prereposetups) 924 > def extsetup(ui): 925 > extensions.wrapfunction(commandserver, b'_serverequest', _serverequest) 926 > EOF 927 $ cat <<EOF >> .hg/hgrc 928 > [extensions] 929 > earlycrasher = ../earlycrasher.py 930 > EOF 931 >>> from hgclient import bprint, check, readchannel, unixserver 932 >>> server = unixserver(b'.hg/server.sock', b'.hg/server.log') 933 >>> def earlycrash(conn): 934 ... while True: 935 ... try: 936 ... ch, data = readchannel(conn) 937 ... for l in data.splitlines(True): 938 ... if not l.startswith(b' '): 939 ... bprint(b'%c, %r' % (ch, l)) 940 ... except EOFError: 941 ... break 942 >>> check(earlycrash, server.connect) 943 e, 'Traceback (most recent call last):\n' 944 e, 'Exception: crash\n' 945 >>> server.shutdown() 946 947 $ cat .hg/server.log | grep -v '^ ' 948 listening at .hg/server.sock 949 Traceback (most recent call last): 950 Exception: crash 951 killed! 952#endif 953#if no-unix-socket 954 955 $ hg serve --cmdserver unix -a .hg/server.sock 956 abort: unsupported platform 957 [255] 958 959#endif 960 961 $ cd .. 962 963Test that accessing to invalid changelog cache is avoided at 964subsequent operations even if repo object is reused even after failure 965of transaction (see 0a7610758c42 also) 966 967"hg log" after failure of transaction is needed to detect invalid 968cache in repoview: this can't detect by "hg verify" only. 969 970Combination of "finalization" and "empty-ness of changelog" (2 x 2 = 9714) are tested, because '00changelog.i' are differently changed in each 972cases. 973 974 $ cat > $TESTTMP/failafterfinalize.py <<EOF 975 > # extension to abort transaction after finalization forcibly 976 > from mercurial import commands, error, extensions, lock as lockmod 977 > from mercurial import registrar 978 > cmdtable = {} 979 > command = registrar.command(cmdtable) 980 > configtable = {} 981 > configitem = registrar.configitem(configtable) 982 > configitem(b'failafterfinalize', b'fail', 983 > default=None, 984 > ) 985 > def fail(tr): 986 > raise error.Abort(b'fail after finalization') 987 > def reposetup(ui, repo): 988 > class failrepo(repo.__class__): 989 > def commitctx(self, ctx, error=False, origctx=None): 990 > if self.ui.configbool(b'failafterfinalize', b'fail'): 991 > # 'sorted()' by ASCII code on category names causes 992 > # invoking 'fail' after finalization of changelog 993 > # using "'cl-%i' % id(self)" as category name 994 > self.currenttransaction().addfinalize(b'zzzzzzzz', fail) 995 > return super(failrepo, self).commitctx(ctx, error, origctx) 996 > repo.__class__ = failrepo 997 > EOF 998 999 $ hg init repo3 1000 $ cd repo3 1001 1002 $ cat <<EOF >> $HGRCPATH 1003 > [command-templates] 1004 > log = {rev} {desc|firstline} ({files})\n 1005 > 1006 > [extensions] 1007 > failafterfinalize = $TESTTMP/failafterfinalize.py 1008 > EOF 1009 1010- test failure with "empty changelog" 1011 1012 $ echo foo > foo 1013 $ hg add foo 1014 1015(failure before finalization) 1016 1017 >>> from hgclient import check, readchannel, runcommand 1018 >>> @check 1019 ... def abort(server): 1020 ... readchannel(server) 1021 ... runcommand(server, [b'commit', 1022 ... b'--config', b'hooks.pretxncommit=false', 1023 ... b'-mfoo']) 1024 ... runcommand(server, [b'log']) 1025 ... runcommand(server, [b'verify', b'-q']) 1026 *** runcommand commit --config hooks.pretxncommit=false -mfoo 1027 transaction abort! 1028 rollback completed 1029 abort: pretxncommit hook exited with status 1 1030 [40] 1031 *** runcommand log 1032 *** runcommand verify -q 1033 1034(failure after finalization) 1035 1036 >>> from hgclient import check, readchannel, runcommand 1037 >>> @check 1038 ... def abort(server): 1039 ... readchannel(server) 1040 ... runcommand(server, [b'commit', 1041 ... b'--config', b'failafterfinalize.fail=true', 1042 ... b'-mfoo']) 1043 ... runcommand(server, [b'log']) 1044 ... runcommand(server, [b'verify', b'-q']) 1045 *** runcommand commit --config failafterfinalize.fail=true -mfoo 1046 transaction abort! 1047 rollback completed 1048 abort: fail after finalization 1049 [255] 1050 *** runcommand log 1051 *** runcommand verify -q 1052 1053- test failure with "not-empty changelog" 1054 1055 $ echo bar > bar 1056 $ hg add bar 1057 $ hg commit -mbar bar 1058 1059(failure before finalization) 1060 1061 >>> from hgclient import check, readchannel, runcommand 1062 >>> @check 1063 ... def abort(server): 1064 ... readchannel(server) 1065 ... runcommand(server, [b'commit', 1066 ... b'--config', b'hooks.pretxncommit=false', 1067 ... b'-mfoo', b'foo']) 1068 ... runcommand(server, [b'log']) 1069 ... runcommand(server, [b'verify', b'-q']) 1070 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo 1071 transaction abort! 1072 rollback completed 1073 abort: pretxncommit hook exited with status 1 1074 [40] 1075 *** runcommand log 1076 0 bar (bar) 1077 *** runcommand verify -q 1078 1079(failure after finalization) 1080 1081 >>> from hgclient import check, readchannel, runcommand 1082 >>> @check 1083 ... def abort(server): 1084 ... readchannel(server) 1085 ... runcommand(server, [b'commit', 1086 ... b'--config', b'failafterfinalize.fail=true', 1087 ... b'-mfoo', b'foo']) 1088 ... runcommand(server, [b'log']) 1089 ... runcommand(server, [b'verify', b'-q']) 1090 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo 1091 transaction abort! 1092 rollback completed 1093 abort: fail after finalization 1094 [255] 1095 *** runcommand log 1096 0 bar (bar) 1097 *** runcommand verify -q 1098 1099 $ cd .. 1100 1101Test symlink traversal over cached audited paths: 1102------------------------------------------------- 1103 1104#if symlink 1105 1106set up symlink hell 1107 1108 $ mkdir merge-symlink-out 1109 $ hg init merge-symlink 1110 $ cd merge-symlink 1111 $ touch base 1112 $ hg commit -qAm base 1113 $ ln -s ../merge-symlink-out a 1114 $ hg commit -qAm 'symlink a -> ../merge-symlink-out' 1115 $ hg up -q 0 1116 $ mkdir a 1117 $ touch a/poisoned 1118 $ hg commit -qAm 'file a/poisoned' 1119 $ hg log -G -T '{rev}: {desc}\n' 1120 @ 2: file a/poisoned 1121 | 1122 | o 1: symlink a -> ../merge-symlink-out 1123 |/ 1124 o 0: base 1125 1126 1127try trivial merge after update: cache of audited paths should be discarded, 1128and the merge should fail (issue5628) 1129 1130 $ hg up -q null 1131 >>> from hgclient import check, readchannel, runcommand 1132 >>> @check 1133 ... def merge(server): 1134 ... readchannel(server) 1135 ... # audit a/poisoned as a good path 1136 ... runcommand(server, [b'up', b'-qC', b'2']) 1137 ... runcommand(server, [b'up', b'-qC', b'1']) 1138 ... # here a is a symlink, so a/poisoned is bad 1139 ... runcommand(server, [b'merge', b'2']) 1140 *** runcommand up -qC 2 1141 *** runcommand up -qC 1 1142 *** runcommand merge 2 1143 abort: path 'a/poisoned' traverses symbolic link 'a' 1144 [255] 1145 $ ls ../merge-symlink-out 1146 1147cache of repo.auditor should be discarded, so matcher would never traverse 1148symlinks: 1149 1150 $ hg up -qC 0 1151 $ touch ../merge-symlink-out/poisoned 1152 >>> from hgclient import check, readchannel, runcommand 1153 >>> @check 1154 ... def files(server): 1155 ... readchannel(server) 1156 ... runcommand(server, [b'up', b'-qC', b'2']) 1157 ... # audit a/poisoned as a good path 1158 ... runcommand(server, [b'files', b'a/poisoned']) 1159 ... runcommand(server, [b'up', b'-qC', b'0']) 1160 ... runcommand(server, [b'up', b'-qC', b'1']) 1161 ... # here 'a' is a symlink, so a/poisoned should be warned 1162 ... runcommand(server, [b'files', b'a/poisoned']) 1163 *** runcommand up -qC 2 1164 *** runcommand files a/poisoned 1165 a/poisoned 1166 *** runcommand up -qC 0 1167 *** runcommand up -qC 1 1168 *** runcommand files a/poisoned 1169 abort: path 'a/poisoned' traverses symbolic link 'a' 1170 [255] 1171 1172 $ cd .. 1173 1174#endif 1175