remote-hg: check if a fetch is needed

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Felipe Contreras committed May 24, 2013 at 21:30 UTC ba091c200d88b27a0bd9027f24a7250f196fc304
2 files changed +109 -1
contrib/remote-helpers/git-remote-hg
+39
@@ -973,6 +973,15 @@ def push(repo, remote, parsed_refs, p_revs):
973
974 return ret
975
976 +def check_tip(ref, kind, name, heads):
977 + try:
978 + ename = '%s/%s' % (kind, name)
979 + tip = marks.get_tip(ename)
980 + except KeyError:
981 + return True
982 + else:
983 + return tip in heads
984 +
985 def do_export(parser):
986 global parsed_refs, bmarks, peer
987
@@ -995,6 +1004,8 @@ def do_export(parser):
1004 else:
1005 die('unhandled export command: %s' % line)
1006
1007 + need_fetch = False
1008 +
1009 for ref, node in parsed_refs.iteritems():
1010 bnode = hgbin(node)
1011 if ref.startswith('refs/heads/branches'):
@@ -1002,6 +1013,16 @@ def do_export(parser):
1013 if branch in branches and bnode in branches[branch]:
1014 # up to date
1015 continue
1016 +
1017 + if peer:
1018 + remotemap = peer.branchmap()
1019 + if remotemap and branch in remotemap:
1020 + heads = [hghex(e) for e in remotemap[branch]]
1021 + if not check_tip(ref, 'branches', branch, heads):
1022 + print "error %s fetch first" % ref
1023 + need_fetch = True
1024 + continue
1025 +
1026 p_revs[bnode] = ref
1027 print "ok %s" % ref
1028 elif ref.startswith('refs/heads/'):
@@ -1017,6 +1038,14 @@ def do_export(parser):
1038 not (bmark == 'master' and bmark not in parser.repo._bookmarks):
1039 p_bmarks.append((ref, bmark, old, new))
1040
1041 + if peer:
1042 + remote_old = peer.listkeys('bookmarks').get(bmark)
1043 + if remote_old:
1044 + if not check_tip(ref, 'bookmarks', bmark, remote_old):
1045 + print "error %s fetch first" % ref
1046 + need_fetch = True
1047 + continue
1048 +
1049 p_revs[bnode] = ref
1050 elif ref.startswith('refs/tags/'):
1051 tag = ref[len('refs/tags/'):]
@@ -1037,6 +1066,16 @@ def do_export(parser):
1066 # transport-helper/fast-export bugs
1067 continue
1068
1069 + if need_fetch:
1070 + print
1071 + return
1072 +
1073 + if dry_run:
1074 + if peer and not force_push:
1075 + checkheads(parser.repo, peer, p_revs)
1076 + print
1077 + return
1078 +
1079 if peer:
1080 if not push(parser.repo, peer, parsed_refs, p_revs):
1081 # do not update bookmarks
contrib/remote-helpers/test-hg.sh
+70 -1
@@ -65,6 +65,9 @@ check_push () {
65 'non-fast-forward')
66 grep "^ ! \[rejected\] *${branch} -> ${branch} (non-fast-forward)$" error || ref_ret=1
67 ;;
68 + 'fetch-first')
69 + grep "^ ! \[rejected\] *${branch} -> ${branch} (fetch first)$" error || ref_ret=1
70 + ;;
71 '')
72 grep "^ [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
73 ;;
@@ -407,7 +410,7 @@ test_expect_success 'remote update bookmark diverge' '
410 echo diverge > content &&
411 git commit -a -m diverge &&
412 check_push 1 <<-EOF
410 - diverge:non-fast-forward
413 + diverge:fetch-first
414 EOF
415 ) &&
416
@@ -525,6 +528,72 @@ test_expect_success 'remote big push' '
528 check_bookmark hgrepo new_bmark ''
529 '
530
531 +test_expect_success 'remote big push fetch first' '
532 + test_when_finished "rm -rf hgrepo gitrepo*" &&
533 +
534 + (
535 + hg init hgrepo &&
536 + cd hgrepo &&
537 + echo zero > content &&
538 + hg add content &&
539 + hg commit -m zero &&
540 + hg bookmark bad_bmark &&
541 + hg bookmark good_bmark &&
542 + hg bookmark -i good_bmark &&
543 + hg -q branch good_branch &&
544 + echo "good branch" > content &&
545 + hg commit -m "good branch" &&
546 + hg -q branch bad_branch &&
547 + echo "bad branch" > content &&
548 + hg commit -m "bad branch"
549 + ) &&
550 +
551 + git clone "hg::hgrepo" gitrepo &&
552 +
553 + (
554 + cd hgrepo &&
555 + hg bookmark -f bad_bmark &&
556 + echo update_bmark > content &&
557 + hg commit -m "update bmark"
558 + ) &&
559 +
560 + (
561 + cd gitrepo &&
562 + echo two > content &&
563 + git commit -q -a -m two &&
564 +
565 + git checkout -q good_bmark &&
566 + echo three > content &&
567 + git commit -q -a -m three &&
568 +
569 + git checkout -q bad_bmark &&
570 + echo four > content &&
571 + git commit -q -a -m four &&
572 +
573 + git checkout -q branches/bad_branch &&
574 + echo five > content &&
575 + git commit -q -a -m five &&
576 +
577 + check_push 1 --all <<-EOF
578 + master
579 + good_bmark
580 + new_bmark:new
581 + new_branch:new
582 + bad_bmark:fetch-first
583 + branches/bad_branch:festch-first
584 + EOF
585 +
586 + git fetch &&
587 +
588 + check_push 1 --all <<-EOF
589 + master
590 + good_bmark
591 + bad_bmark:non-fast-forward
592 + branches/bad_branch:non-fast-forward
593 + EOF
594 + )
595 +'
596 +
597 test_expect_success 'remote double failed push' '
598 test_when_finished "rm -rf hgrepo gitrepo*" &&
599