remote-hg: implement custom checkheads()

The version from Mercurial is extremely inefficient and convoluted, this version achieves basically the same, at least for our purposes. No functional changes. 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:29 UTC 19a8cefc44b216db5cf8faf790d197c85db6395e
1 file changed +49 -3
contrib/remote-helpers/git-remote-hg
+49 -3
@@ -12,7 +12,7 @@
12 # For remote repositories a local clone is stored in
13 # "$GIT_DIR/hg/origin/clone/.hg/".
14
15 -from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery
15 +from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery, util
16
17 import re
18 import sys
@@ -86,6 +86,11 @@ def hgref(ref):
86 def gitref(ref):
87 return ref.replace(' ', '___')
88
89 +def check_version(*check):
90 + if not hg_version:
91 + return True
92 + return hg_version >= check
93 +
94 def get_config(config):
95 cmd = ['git', 'config', '--get', config]
96 process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
@@ -854,6 +859,42 @@ def write_tag(repo, tag, node, msg, author):
859
860 return tagnode
861
862 +def checkheads(repo, remote, p_revs):
863 +
864 + remotemap = remote.branchmap()
865 + if not remotemap:
866 + # empty repo
867 + return
868 +
869 + new = {}
870 +
871 + for node in p_revs:
872 + ctx = repo[node]
873 + branch = ctx.branch()
874 + if not branch in remotemap:
875 + # new branch
876 + continue
877 + new.setdefault(branch, []).append(ctx.rev())
878 +
879 + for branch, heads in new.iteritems():
880 + old = [repo.changelog.rev(x) for x in remotemap[branch]]
881 + for rev in heads:
882 + if check_version(2, 3):
883 + ancestors = repo.changelog.ancestors([rev], stoprev=min(old))
884 + else:
885 + ancestors = repo.changelog.ancestors(rev)
886 + found = False
887 +
888 + for x in old:
889 + if x in ancestors:
890 + found = True
891 + break
892 +
893 + if found:
894 + continue
895 +
896 + raise Exception("non-fast-forward")
897 +
898 def push_unsafe(repo, remote, parsed_refs, p_revs):
899
900 force = force_push
@@ -862,7 +903,8 @@ def push_unsafe(repo, remote, parsed_refs, p_revs):
903 commoninc = fci(repo, remote, force=force)
904 common, _, remoteheads = commoninc
905
865 - # TODO checkheads
906 + if not force:
907 + checkheads(repo, remote, p_revs)
908
909 cg = repo.getbundle('push', heads=list(p_revs), common=common)
910
@@ -991,7 +1033,7 @@ def main(args):
1033 global track_branches, force_push, is_tmp
1034 global parsed_tags
1035 global filenodes
994 - global fake_bmark
1036 + global fake_bmark, hg_version
1037
1038 alias = args[1]
1039 url = args[2]
@@ -1026,6 +1068,10 @@ def main(args):
1068 parsed_tags = {}
1069 filenodes = {}
1070 fake_bmark = None
1071 + try:
1072 + hg_version = tuple(int(e) for e in util.version().split('.'))
1073 + except:
1074 + hg_version = None
1075
1076 repo = get_repo(url, alias)
1077 prefix = 'refs/hg/%s' % alias