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