remote-hg: implement custom push()
[gitweb.git] / contrib / remote-helpers / git-remote-hg
index 7added3b332d1f36af3e18e80bbaa8abcdcbe4b0..c2c1cb8b52b307b6213e440c17075959757ab4fb 100755 (executable)
@@ -12,7 +12,7 @@
 # For remote repositories a local clone is stored in
 # "$GIT_DIR/hg/origin/clone/.hg/".
 
-from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions
+from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery
 
 import re
 import sys
@@ -854,6 +854,46 @@ def write_tag(repo, tag, node, msg, author):
 
     return tagnode
 
+def push_unsafe(repo, remote, parsed_refs, p_revs):
+
+    force = force_push
+
+    fci = discovery.findcommonincoming
+    commoninc = fci(repo, remote, force=force)
+    common, _, remoteheads = commoninc
+
+    # TODO checkheads
+
+    cg = repo.getbundle('push', heads=list(p_revs), common=common)
+
+    unbundle = remote.capable('unbundle')
+    if unbundle:
+        if force:
+            remoteheads = ['force']
+        return remote.unbundle(cg, remoteheads, 'push')
+    else:
+        return remote.addchangegroup(cg, 'push', repo.url())
+
+def push(repo, remote, parsed_refs, p_revs):
+    if hasattr(remote, 'canpush') and not remote.canpush():
+        print "error cannot push"
+
+    if not p_revs:
+        # nothing to push
+        return
+
+    lock = None
+    unbundle = remote.capable('unbundle')
+    if not unbundle:
+        lock = remote.lock()
+    try:
+        ret = push_unsafe(repo, remote, parsed_refs, p_revs)
+    finally:
+        if lock is not None:
+            lock.release()
+
+    return ret
+
 def do_export(parser):
     global parsed_refs, bmarks, peer
 
@@ -919,7 +959,7 @@ def do_export(parser):
             continue
 
     if peer:
-        parser.repo.push(peer, force=force_push, newbranch=True, revs=list(p_revs))
+        push(parser.repo, peer, parsed_refs, p_revs)
 
         # update remote bookmarks
         remote_bmarks = peer.listkeys('bookmarks')