[PATCH 1 of 2 bfiles] httpstore: monkey patch HTTP handler to make requests with arbitrary methods

Geoff Crossland geoff.crossland at linguamatics.com
Tue Jul 5 08:22:18 CDT 2011


# HG changeset patch
# User Geoff Crossland <gcrossland at linguamatics.com>
# Date 1309869512 -3600
# Node ID ebccf967f84db866f6f0d7a1ae9dd2c59c49d3d7
# Parent  f0512849f1634922b6edccc162e9553b45f56b37
httpstore: monkey patch HTTP handler to make requests with arbitrary methods

diff --git a/bfiles/httpstore.py b/bfiles/httpstore.py
--- a/bfiles/httpstore.py
+++ b/bfiles/httpstore.py
@@ -7,6 +7,42 @@
 from mercurial import util, url as url_
 import bfutil, basestore
 
+# mercurial.keepalive.KeepAliveHandler._start_transaction() doesn't get the HTTP
+# method via urllib2.Request.get_method() as it should do, so we monkey-patch it
+# to do the right thing.
+import sys
+import socket
+import mercurial.keepalive
+def _start_transaction(self, h, req):
+    # What follows mostly reimplements HTTPConnection.request()
+    # except it adds self.parent.addheaders in the mix.
+    headers = req.headers.copy()
+    if sys.version_info >= (2, 4):
+        headers.update(req.unredirected_hdrs)
+    headers.update(self.parent.addheaders)
+    headers = dict((n.lower(), v) for n, v in headers.items())
+    skipheaders = {}
+    for n in ('host', 'accept-encoding'):
+        if n in headers:
+            skipheaders['skip_' + n.replace('-', '_')] = 1
+    try:
+        h.putrequest(req.get_method(), req.get_selector(), **skipheaders)
+        if req.has_data():
+            data = req.get_data()
+            if 'content-type' not in headers:
+                h.putheader('Content-type',
+                            'application/x-www-form-urlencoded')
+            if 'content-length' not in headers:
+                h.putheader('Content-length', '%d' % len(data))
+    except (socket.error), err:
+        raise urllib2.URLError(err)
+    for k, v in headers.items():
+        h.putheader(k, v)
+    h.endheaders()
+    if req.has_data():
+        h.send(data)
+mercurial.keepalive.KeepAliveHandler._start_transaction = _start_transaction
+
 class httpstore(basestore.basestore):
     def __init__(self, ui, repo, url):
         self.ui = ui


More information about the Mercurial-devel mailing list