Show More
@@ -1323,6 +1323,8 b' def getrepocaps(repo, allowpushback=Fals' | |||||
1323 | caps['obsmarkers'] = supportedformat |
|
1323 | caps['obsmarkers'] = supportedformat | |
1324 | if allowpushback: |
|
1324 | if allowpushback: | |
1325 | caps['pushback'] = () |
|
1325 | caps['pushback'] = () | |
|
1326 | if not repo.ui.configbool('experimental', 'checkheads-strict', True): | |||
|
1327 | caps['checkheads'] = ('related',) | |||
1326 | return caps |
|
1328 | return caps | |
1327 |
|
1329 | |||
1328 | def bundle2caps(remote): |
|
1330 | def bundle2caps(remote): | |
@@ -1603,6 +1605,35 b' def handlecheckheads(op, inpart):' | |||||
1603 | raise error.PushRaced('repository changed while pushing - ' |
|
1605 | raise error.PushRaced('repository changed while pushing - ' | |
1604 | 'please try again') |
|
1606 | 'please try again') | |
1605 |
|
1607 | |||
|
1608 | @parthandler('check:updated-heads') | |||
|
1609 | def handlecheckupdatedheads(op, inpart): | |||
|
1610 | """check for race on the heads touched by a push | |||
|
1611 | ||||
|
1612 | This is similar to 'check:heads' but focus on the heads actually updated | |||
|
1613 | during the push. If other activities happen on unrelated heads, it is | |||
|
1614 | ignored. | |||
|
1615 | ||||
|
1616 | This allow server with high traffic to avoid push contention as long as | |||
|
1617 | unrelated parts of the graph are involved.""" | |||
|
1618 | h = inpart.read(20) | |||
|
1619 | heads = [] | |||
|
1620 | while len(h) == 20: | |||
|
1621 | heads.append(h) | |||
|
1622 | h = inpart.read(20) | |||
|
1623 | assert not h | |||
|
1624 | # trigger a transaction so that we are guaranteed to have the lock now. | |||
|
1625 | if op.ui.configbool('experimental', 'bundle2lazylocking'): | |||
|
1626 | op.gettransaction() | |||
|
1627 | ||||
|
1628 | currentheads = set() | |||
|
1629 | for ls in op.repo.branchmap().itervalues(): | |||
|
1630 | currentheads.update(ls) | |||
|
1631 | ||||
|
1632 | for h in heads: | |||
|
1633 | if h not in currentheads: | |||
|
1634 | raise error.PushRaced('repository changed while pushing - ' | |||
|
1635 | 'please try again') | |||
|
1636 | ||||
1606 | @parthandler('output') |
|
1637 | @parthandler('output') | |
1607 | def handleoutput(op, inpart): |
|
1638 | def handleoutput(op, inpart): | |
1608 | """forward output captured on the server to the client""" |
|
1639 | """forward output captured on the server to the client""" |
@@ -332,6 +332,7 b' def checkheads(pushop):' | |||||
332 | headssum = _headssummary(pushop) |
|
332 | headssum = _headssummary(pushop) | |
333 | else: |
|
333 | else: | |
334 | headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) |
|
334 | headssum = _oldheadssummary(repo, remoteheads, outgoing, inc) | |
|
335 | pushop.pushbranchmap = headssum | |||
335 | newbranches = [branch for branch, heads in headssum.iteritems() |
|
336 | newbranches = [branch for branch, heads in headssum.iteritems() | |
336 | if heads[0] is None] |
|
337 | if heads[0] is None] | |
337 | # 1. Check for new branches on the remote. |
|
338 | # 1. Check for new branches on the remote. |
@@ -323,8 +323,21 b' class pushoperation(object):' | |||||
323 | self.bkresult = None |
|
323 | self.bkresult = None | |
324 | # discover.outgoing object (contains common and outgoing data) |
|
324 | # discover.outgoing object (contains common and outgoing data) | |
325 | self.outgoing = None |
|
325 | self.outgoing = None | |
326 | # all remote heads before the push |
|
326 | # all remote topological heads before the push | |
327 | self.remoteheads = None |
|
327 | self.remoteheads = None | |
|
328 | # Details of the remote branch pre and post push | |||
|
329 | # | |||
|
330 | # mapping: {'branch': ([remoteheads], | |||
|
331 | # [newheads], | |||
|
332 | # [unsyncedheads], | |||
|
333 | # [discardedheads])} | |||
|
334 | # - branch: the branch name | |||
|
335 | # - remoteheads: the list of remote heads known locally | |||
|
336 | # None if the branch is new | |||
|
337 | # - newheads: the new remote heads (known locally) with outgoing pushed | |||
|
338 | # - unsyncedheads: the list of remote heads unknown locally. | |||
|
339 | # - discardedheads: the list of remote heads made obsolete by the push | |||
|
340 | self.pushbranchmap = None | |||
328 | # testable as a boolean indicating if any nodes are missing locally. |
|
341 | # testable as a boolean indicating if any nodes are missing locally. | |
329 | self.incoming = None |
|
342 | self.incoming = None | |
330 | # phases changes that must be pushed along side the changesets |
|
343 | # phases changes that must be pushed along side the changesets | |
@@ -712,8 +725,23 b' def _pushb2ctxcheckheads(pushop, bundler' | |||||
712 |
|
725 | |||
713 | Exists as an independent function to aid extensions |
|
726 | Exists as an independent function to aid extensions | |
714 | """ |
|
727 | """ | |
715 | if not pushop.force: |
|
728 | # * 'force' do not check for push race, | |
716 | bundler.newpart('check:heads', data=iter(pushop.remoteheads)) |
|
729 | # * if we don't push anything, there are nothing to check. | |
|
730 | if not pushop.force and pushop.outgoing.missingheads: | |||
|
731 | allowunrelated = 'related' in bundler.capabilities.get('checkheads', ()) | |||
|
732 | if not allowunrelated: | |||
|
733 | bundler.newpart('check:heads', data=iter(pushop.remoteheads)) | |||
|
734 | else: | |||
|
735 | affected = set() | |||
|
736 | for branch, heads in pushop.pushbranchmap.iteritems(): | |||
|
737 | remoteheads, newheads, unsyncedheads, discardedheads = heads | |||
|
738 | if remoteheads is not None: | |||
|
739 | remote = set(remoteheads) | |||
|
740 | affected |= set(discardedheads) & remote | |||
|
741 | affected |= remote - set(newheads) | |||
|
742 | if affected: | |||
|
743 | data = iter(sorted(affected)) | |||
|
744 | bundler.newpart('check:updated-heads', data=data) | |||
717 |
|
745 | |||
718 | @b2partsgenerator('changeset') |
|
746 | @b2partsgenerator('changeset') | |
719 | def _pushb2ctx(pushop, bundler): |
|
747 | def _pushb2ctx(pushop, bundler): |
@@ -102,6 +102,21 b' A set of extension and shell functions e' | |||||
102 | > graph = log -G --rev 'sort(all(), "topo")' |
|
102 | > graph = log -G --rev 'sort(all(), "topo")' | |
103 | > EOF |
|
103 | > EOF | |
104 |
|
104 | |||
|
105 | We tests multiple cases: | |||
|
106 | * strict: no race detected, | |||
|
107 | * unrelated: race on unrelated heads are allowed. | |||
|
108 | ||||
|
109 | #testcases strict unrelated | |||
|
110 | ||||
|
111 | #if unrelated | |||
|
112 | ||||
|
113 | $ cat >> $HGRCPATH << EOF | |||
|
114 | > [experimental] | |||
|
115 | > checkheads-strict = no | |||
|
116 | > EOF | |||
|
117 | ||||
|
118 | #endif | |||
|
119 | ||||
105 | Setup |
|
120 | Setup | |
106 | ----- |
|
121 | ----- | |
107 |
|
122 | |||
@@ -265,6 +280,7 b' Pushing' | |||||
265 |
|
280 | |||
266 | Check the result of the push |
|
281 | Check the result of the push | |
267 |
|
282 | |||
|
283 | #if strict | |||
268 | $ cat ./push-log |
|
284 | $ cat ./push-log | |
269 | pushing to ssh://user@dummy/server |
|
285 | pushing to ssh://user@dummy/server | |
270 | searching for changes |
|
286 | searching for changes | |
@@ -282,6 +298,34 b' Check the result of the push' | |||||
282 | |/ |
|
298 | |/ | |
283 | @ 842e2fac6304 C-ROOT (default) |
|
299 | @ 842e2fac6304 C-ROOT (default) | |
284 |
|
300 | |||
|
301 | #endif | |||
|
302 | #if unrelated | |||
|
303 | ||||
|
304 | (The two heads are unrelated, push should be allowed) | |||
|
305 | ||||
|
306 | $ cat ./push-log | |||
|
307 | pushing to ssh://user@dummy/server | |||
|
308 | searching for changes | |||
|
309 | wrote ready: $TESTTMP/readyfile | |||
|
310 | waiting on: $TESTTMP/watchfile | |||
|
311 | remote: adding changesets | |||
|
312 | remote: adding manifests | |||
|
313 | remote: adding file changes | |||
|
314 | remote: added 1 changesets with 1 changes to 1 files | |||
|
315 | ||||
|
316 | $ hg -R server graph | |||
|
317 | o 59e76faf78bd C-D (default) | |||
|
318 | | | |||
|
319 | o a9149a1428e2 C-B (default) | |||
|
320 | | | |||
|
321 | | o 51c544a58128 C-C (default) | |||
|
322 | | | | |||
|
323 | | o 98217d5a1659 C-A (default) | |||
|
324 | |/ | |||
|
325 | @ 842e2fac6304 C-ROOT (default) | |||
|
326 | ||||
|
327 | #endif | |||
|
328 | ||||
285 | Pushing while someone creates a new head |
|
329 | Pushing while someone creates a new head | |
286 | ----------------------------------------- |
|
330 | ----------------------------------------- | |
287 |
|
331 | |||
@@ -295,6 +339,8 b' Pushing a new changeset while someone cr' | |||||
295 |
|
339 | |||
296 | (resync-all) |
|
340 | (resync-all) | |
297 |
|
341 | |||
|
342 | #if strict | |||
|
343 | ||||
298 | $ hg -R ./server pull ./client-racy |
|
344 | $ hg -R ./server pull ./client-racy | |
299 | pulling from ./client-racy |
|
345 | pulling from ./client-racy | |
300 | searching for changes |
|
346 | searching for changes | |
@@ -303,6 +349,17 b' Pushing a new changeset while someone cr' | |||||
303 | adding file changes |
|
349 | adding file changes | |
304 | added 1 changesets with 1 changes to 1 files |
|
350 | added 1 changesets with 1 changes to 1 files | |
305 | (run 'hg update' to get a working copy) |
|
351 | (run 'hg update' to get a working copy) | |
|
352 | ||||
|
353 | #endif | |||
|
354 | #if unrelated | |||
|
355 | ||||
|
356 | $ hg -R ./server pull ./client-racy | |||
|
357 | pulling from ./client-racy | |||
|
358 | searching for changes | |||
|
359 | no changes found | |||
|
360 | ||||
|
361 | #endif | |||
|
362 | ||||
306 |
$ |
|
363 | $ hg -R ./client-other pull | |
307 | pulling from ssh://user@dummy/server |
|
364 | pulling from ssh://user@dummy/server | |
308 | searching for changes |
|
365 | searching for changes | |
@@ -367,6 +424,8 b' Pushing' | |||||
367 |
|
424 | |||
368 | Check the result of the push |
|
425 | Check the result of the push | |
369 |
|
426 | |||
|
427 | #if strict | |||
|
428 | ||||
370 | $ cat ./push-log |
|
429 | $ cat ./push-log | |
371 | pushing to ssh://user@dummy/server |
|
430 | pushing to ssh://user@dummy/server | |
372 | searching for changes |
|
431 | searching for changes | |
@@ -389,6 +448,39 b' Check the result of the push' | |||||
389 | @ 842e2fac6304 C-ROOT (default) |
|
448 | @ 842e2fac6304 C-ROOT (default) | |
390 |
|
449 | |||
391 |
|
450 | |||
|
451 | #endif | |||
|
452 | ||||
|
453 | #if unrelated | |||
|
454 | ||||
|
455 | (The racing new head do not affect existing heads, push should go through) | |||
|
456 | ||||
|
457 | $ cat ./push-log | |||
|
458 | pushing to ssh://user@dummy/server | |||
|
459 | searching for changes | |||
|
460 | wrote ready: $TESTTMP/readyfile | |||
|
461 | waiting on: $TESTTMP/watchfile | |||
|
462 | remote: adding changesets | |||
|
463 | remote: adding manifests | |||
|
464 | remote: adding file changes | |||
|
465 | remote: added 1 changesets with 1 changes to 1 files | |||
|
466 | ||||
|
467 | $ hg -R server graph | |||
|
468 | o d9e379a8c432 C-F (default) | |||
|
469 | | | |||
|
470 | o 51c544a58128 C-C (default) | |||
|
471 | | | |||
|
472 | | o d603e2c0cdd7 C-E (default) | |||
|
473 | |/ | |||
|
474 | o 98217d5a1659 C-A (default) | |||
|
475 | | | |||
|
476 | | o 59e76faf78bd C-D (default) | |||
|
477 | | | | |||
|
478 | | o a9149a1428e2 C-B (default) | |||
|
479 | |/ | |||
|
480 | @ 842e2fac6304 C-ROOT (default) | |||
|
481 | ||||
|
482 | #endif | |||
|
483 | ||||
392 | Pushing touching different named branch (same topo): new branch raced |
|
484 | Pushing touching different named branch (same topo): new branch raced | |
393 | --------------------------------------------------------------------- |
|
485 | --------------------------------------------------------------------- | |
394 |
|
486 | |||
@@ -402,6 +494,8 b' Pushing two children on the same head, o' | |||||
402 |
|
494 | |||
403 | (resync-all) |
|
495 | (resync-all) | |
404 |
|
496 | |||
|
497 | #if strict | |||
|
498 | ||||
405 | $ hg -R ./server pull ./client-racy |
|
499 | $ hg -R ./server pull ./client-racy | |
406 | pulling from ./client-racy |
|
500 | pulling from ./client-racy | |
407 | searching for changes |
|
501 | searching for changes | |
@@ -410,6 +504,17 b' Pushing two children on the same head, o' | |||||
410 | adding file changes |
|
504 | adding file changes | |
411 | added 1 changesets with 1 changes to 1 files |
|
505 | added 1 changesets with 1 changes to 1 files | |
412 | (run 'hg update' to get a working copy) |
|
506 | (run 'hg update' to get a working copy) | |
|
507 | ||||
|
508 | #endif | |||
|
509 | #if unrelated | |||
|
510 | ||||
|
511 | $ hg -R ./server pull ./client-racy | |||
|
512 | pulling from ./client-racy | |||
|
513 | searching for changes | |||
|
514 | no changes found | |||
|
515 | ||||
|
516 | #endif | |||
|
517 | ||||
413 |
$ |
|
518 | $ hg -R ./client-other pull | |
414 | pulling from ssh://user@dummy/server |
|
519 | pulling from ssh://user@dummy/server | |
415 | searching for changes |
|
520 | searching for changes | |
@@ -480,6 +585,7 b' Pushing' | |||||
480 |
|
585 | |||
481 | Check the result of the push |
|
586 | Check the result of the push | |
482 |
|
587 | |||
|
588 | #if strict | |||
483 | $ cat ./push-log |
|
589 | $ cat ./push-log | |
484 | pushing to ssh://user@dummy/server |
|
590 | pushing to ssh://user@dummy/server | |
485 | searching for changes |
|
591 | searching for changes | |
@@ -505,6 +611,43 b' Check the result of the push' | |||||
505 | |/ |
|
611 | |/ | |
506 | @ 842e2fac6304 C-ROOT (default) |
|
612 | @ 842e2fac6304 C-ROOT (default) | |
507 |
|
613 | |||
|
614 | #endif | |||
|
615 | #if unrelated | |||
|
616 | ||||
|
617 | (unrelated named branches are unrelated) | |||
|
618 | ||||
|
619 | $ cat ./push-log | |||
|
620 | pushing to ssh://user@dummy/server | |||
|
621 | searching for changes | |||
|
622 | wrote ready: $TESTTMP/readyfile | |||
|
623 | waiting on: $TESTTMP/watchfile | |||
|
624 | remote: adding changesets | |||
|
625 | remote: adding manifests | |||
|
626 | remote: adding file changes | |||
|
627 | remote: added 1 changesets with 1 changes to 1 files (+1 heads) | |||
|
628 | ||||
|
629 | $ hg -R server graph | |||
|
630 | o 833be552cfe6 C-H (my-first-test-branch) | |||
|
631 | | | |||
|
632 | | o 75d69cba5402 C-G (default) | |||
|
633 | |/ | |||
|
634 | o d9e379a8c432 C-F (default) | |||
|
635 | | | |||
|
636 | o 51c544a58128 C-C (default) | |||
|
637 | | | |||
|
638 | | o d603e2c0cdd7 C-E (default) | |||
|
639 | |/ | |||
|
640 | o 98217d5a1659 C-A (default) | |||
|
641 | | | |||
|
642 | | o 59e76faf78bd C-D (default) | |||
|
643 | | | | |||
|
644 | | o a9149a1428e2 C-B (default) | |||
|
645 | |/ | |||
|
646 | @ 842e2fac6304 C-ROOT (default) | |||
|
647 | ||||
|
648 | #endif | |||
|
649 | ||||
|
650 | The racing new head do not affect existing heads, push should go through | |||
508 |
|
651 | |||
509 | pushing touching different named branch (same topo): old branch raced |
|
652 | pushing touching different named branch (same topo): old branch raced | |
510 | --------------------------------------------------------------------- |
|
653 | --------------------------------------------------------------------- | |
@@ -519,6 +662,8 b' Pushing two children on the same head, o' | |||||
519 |
|
662 | |||
520 | (resync-all) |
|
663 | (resync-all) | |
521 |
|
664 | |||
|
665 | #if strict | |||
|
666 | ||||
522 | $ hg -R ./server pull ./client-racy |
|
667 | $ hg -R ./server pull ./client-racy | |
523 | pulling from ./client-racy |
|
668 | pulling from ./client-racy | |
524 | searching for changes |
|
669 | searching for changes | |
@@ -527,6 +672,17 b' Pushing two children on the same head, o' | |||||
527 | adding file changes |
|
672 | adding file changes | |
528 | added 1 changesets with 1 changes to 1 files (+1 heads) |
|
673 | added 1 changesets with 1 changes to 1 files (+1 heads) | |
529 | (run 'hg heads .' to see heads, 'hg merge' to merge) |
|
674 | (run 'hg heads .' to see heads, 'hg merge' to merge) | |
|
675 | ||||
|
676 | #endif | |||
|
677 | #if unrelated | |||
|
678 | ||||
|
679 | $ hg -R ./server pull ./client-racy | |||
|
680 | pulling from ./client-racy | |||
|
681 | searching for changes | |||
|
682 | no changes found | |||
|
683 | ||||
|
684 | #endif | |||
|
685 | ||||
530 |
$ |
|
686 | $ hg -R ./client-other pull | |
531 | pulling from ssh://user@dummy/server |
|
687 | pulling from ssh://user@dummy/server | |
532 | searching for changes |
|
688 | searching for changes | |
@@ -600,6 +756,8 b' Pushing' | |||||
600 |
|
756 | |||
601 | Check the result of the push |
|
757 | Check the result of the push | |
602 |
|
758 | |||
|
759 | #if strict | |||
|
760 | ||||
603 | $ cat ./push-log |
|
761 | $ cat ./push-log | |
604 | pushing to ssh://user@dummy/server |
|
762 | pushing to ssh://user@dummy/server | |
605 | searching for changes |
|
763 | searching for changes | |
@@ -630,6 +788,48 b' Check the result of the push' | |||||
630 | @ 842e2fac6304 C-ROOT (default) |
|
788 | @ 842e2fac6304 C-ROOT (default) | |
631 |
|
789 | |||
632 |
|
790 | |||
|
791 | #endif | |||
|
792 | ||||
|
793 | #if unrelated | |||
|
794 | ||||
|
795 | (unrelated named branches are unrelated) | |||
|
796 | ||||
|
797 | $ cat ./push-log | |||
|
798 | pushing to ssh://user@dummy/server | |||
|
799 | searching for changes | |||
|
800 | wrote ready: $TESTTMP/readyfile | |||
|
801 | waiting on: $TESTTMP/watchfile | |||
|
802 | remote: adding changesets | |||
|
803 | remote: adding manifests | |||
|
804 | remote: adding file changes | |||
|
805 | remote: added 1 changesets with 1 changes to 1 files (+1 heads) | |||
|
806 | ||||
|
807 | $ hg -R server graph | |||
|
808 | o 89420bf00fae C-J (default) | |||
|
809 | | | |||
|
810 | | o b35ed749f288 C-I (my-second-test-branch) | |||
|
811 | |/ | |||
|
812 | o 75d69cba5402 C-G (default) | |||
|
813 | | | |||
|
814 | | o 833be552cfe6 C-H (my-first-test-branch) | |||
|
815 | |/ | |||
|
816 | o d9e379a8c432 C-F (default) | |||
|
817 | | | |||
|
818 | o 51c544a58128 C-C (default) | |||
|
819 | | | |||
|
820 | | o d603e2c0cdd7 C-E (default) | |||
|
821 | |/ | |||
|
822 | o 98217d5a1659 C-A (default) | |||
|
823 | | | |||
|
824 | | o 59e76faf78bd C-D (default) | |||
|
825 | | | | |||
|
826 | | o a9149a1428e2 C-B (default) | |||
|
827 | |/ | |||
|
828 | @ 842e2fac6304 C-ROOT (default) | |||
|
829 | ||||
|
830 | ||||
|
831 | #endif | |||
|
832 | ||||
633 | pushing racing push touch multiple heads |
|
833 | pushing racing push touch multiple heads | |
634 | ---------------------------------------- |
|
834 | ---------------------------------------- | |
635 |
|
835 | |||
@@ -644,6 +844,8 b' There are multiple heads, but the racing' | |||||
644 |
|
844 | |||
645 | (resync-all) |
|
845 | (resync-all) | |
646 |
|
846 | |||
|
847 | #if strict | |||
|
848 | ||||
647 | $ hg -R ./server pull ./client-racy |
|
849 | $ hg -R ./server pull ./client-racy | |
648 | pulling from ./client-racy |
|
850 | pulling from ./client-racy | |
649 | searching for changes |
|
851 | searching for changes | |
@@ -652,6 +854,18 b' There are multiple heads, but the racing' | |||||
652 | adding file changes |
|
854 | adding file changes | |
653 | added 1 changesets with 1 changes to 1 files (+1 heads) |
|
855 | added 1 changesets with 1 changes to 1 files (+1 heads) | |
654 | (run 'hg heads .' to see heads, 'hg merge' to merge) |
|
856 | (run 'hg heads .' to see heads, 'hg merge' to merge) | |
|
857 | ||||
|
858 | #endif | |||
|
859 | ||||
|
860 | #if unrelated | |||
|
861 | ||||
|
862 | $ hg -R ./server pull ./client-racy | |||
|
863 | pulling from ./client-racy | |||
|
864 | searching for changes | |||
|
865 | no changes found | |||
|
866 | ||||
|
867 | #endif | |||
|
868 | ||||
655 |
$ |
|
869 | $ hg -R ./client-other pull | |
656 | pulling from ssh://user@dummy/server |
|
870 | pulling from ssh://user@dummy/server | |
657 | searching for changes |
|
871 | searching for changes |
General Comments 0
You need to be logged in to leave comments.
Login now