summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/remote-helpers/git-remote-hg39
-rwxr-xr-xcontrib/remote-helpers/test-hg.sh71
2 files changed, 109 insertions, 1 deletions
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index b08f909076..b983627ce3 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -973,6 +973,15 @@ def push(repo, remote, parsed_refs, p_revs):
return ret
+def check_tip(ref, kind, name, heads):
+ try:
+ ename = '%s/%s' % (kind, name)
+ tip = marks.get_tip(ename)
+ except KeyError:
+ return True
+ else:
+ return tip in heads
+
def do_export(parser):
global parsed_refs, bmarks, peer
@@ -995,6 +1004,8 @@ def do_export(parser):
else:
die('unhandled export command: %s' % line)
+ need_fetch = False
+
for ref, node in parsed_refs.iteritems():
bnode = hgbin(node)
if ref.startswith('refs/heads/branches'):
@@ -1002,6 +1013,16 @@ def do_export(parser):
if branch in branches and bnode in branches[branch]:
# up to date
continue
+
+ if peer:
+ remotemap = peer.branchmap()
+ if remotemap and branch in remotemap:
+ heads = [hghex(e) for e in remotemap[branch]]
+ if not check_tip(ref, 'branches', branch, heads):
+ print "error %s fetch first" % ref
+ need_fetch = True
+ continue
+
p_revs[bnode] = ref
print "ok %s" % ref
elif ref.startswith('refs/heads/'):
@@ -1017,6 +1038,14 @@ def do_export(parser):
not (bmark == 'master' and bmark not in parser.repo._bookmarks):
p_bmarks.append((ref, bmark, old, new))
+ if peer:
+ remote_old = peer.listkeys('bookmarks').get(bmark)
+ if remote_old:
+ if not check_tip(ref, 'bookmarks', bmark, remote_old):
+ print "error %s fetch first" % ref
+ need_fetch = True
+ continue
+
p_revs[bnode] = ref
elif ref.startswith('refs/tags/'):
tag = ref[len('refs/tags/'):]
@@ -1037,6 +1066,16 @@ def do_export(parser):
# transport-helper/fast-export bugs
continue
+ if need_fetch:
+ print
+ return
+
+ if dry_run:
+ if peer and not force_push:
+ checkheads(parser.repo, peer, p_revs)
+ print
+ return
+
if peer:
if not push(parser.repo, peer, parsed_refs, p_revs):
# do not update bookmarks
diff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh
index 53d2504e12..41ea2e8083 100755
--- a/contrib/remote-helpers/test-hg.sh
+++ b/contrib/remote-helpers/test-hg.sh
@@ -65,6 +65,9 @@ check_push () {
'non-fast-forward')
grep "^ ! \[rejected\] *${branch} -> ${branch} (non-fast-forward)$" error || ref_ret=1
;;
+ 'fetch-first')
+ grep "^ ! \[rejected\] *${branch} -> ${branch} (fetch first)$" error || ref_ret=1
+ ;;
'')
grep "^ [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
;;
@@ -407,7 +410,7 @@ test_expect_success 'remote update bookmark diverge' '
echo diverge > content &&
git commit -a -m diverge &&
check_push 1 <<-EOF
- diverge:non-fast-forward
+ diverge:fetch-first
EOF
) &&
@@ -525,6 +528,72 @@ test_expect_success 'remote big push' '
check_bookmark hgrepo new_bmark ''
'
+test_expect_success 'remote big push fetch first' '
+ test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+ (
+ hg init hgrepo &&
+ cd hgrepo &&
+ echo zero > content &&
+ hg add content &&
+ hg commit -m zero &&
+ hg bookmark bad_bmark &&
+ hg bookmark good_bmark &&
+ hg bookmark -i good_bmark &&
+ hg -q branch good_branch &&
+ echo "good branch" > content &&
+ hg commit -m "good branch" &&
+ hg -q branch bad_branch &&
+ echo "bad branch" > content &&
+ hg commit -m "bad branch"
+ ) &&
+
+ git clone "hg::hgrepo" gitrepo &&
+
+ (
+ cd hgrepo &&
+ hg bookmark -f bad_bmark &&
+ echo update_bmark > content &&
+ hg commit -m "update bmark"
+ ) &&
+
+ (
+ cd gitrepo &&
+ echo two > content &&
+ git commit -q -a -m two &&
+
+ git checkout -q good_bmark &&
+ echo three > content &&
+ git commit -q -a -m three &&
+
+ git checkout -q bad_bmark &&
+ echo four > content &&
+ git commit -q -a -m four &&
+
+ git checkout -q branches/bad_branch &&
+ echo five > content &&
+ git commit -q -a -m five &&
+
+ check_push 1 --all <<-EOF
+ master
+ good_bmark
+ new_bmark:new
+ new_branch:new
+ bad_bmark:fetch-first
+ branches/bad_branch:festch-first
+ EOF
+
+ git fetch &&
+
+ check_push 1 --all <<-EOF
+ master
+ good_bmark
+ bad_bmark:non-fast-forward
+ branches/bad_branch:non-fast-forward
+ EOF
+ )
+'
+
test_expect_success 'remote double failed push' '
test_when_finished "rm -rf hgrepo gitrepo*" &&