Mercurial > hg
changeset 2465:c91118f425d0
push over http: client support.
stream bundle data using PUT request.
author | Vadim Gelfer <vadim.gelfer@gmail.com> |
---|---|
date | Tue, 20 Jun 2006 15:17:28 -0700 |
parents | 09b1c9ef317c |
children | e10665147d26 |
files | mercurial/httprepo.py |
diffstat | 1 files changed, 46 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/httprepo.py Tue Jun 20 15:16:50 2006 -0700 +++ b/mercurial/httprepo.py Tue Jun 20 15:17:28 2006 -0700 @@ -10,7 +10,7 @@ from i18n import gettext as _ from demandload import * demandload(globals(), "hg os urllib urllib2 urlparse zlib util httplib") -demandload(globals(), "keepalive") +demandload(globals(), "keepalive tempfile socket") class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm): def __init__(self, ui): @@ -69,6 +69,22 @@ return userpass + '@' + hostport return hostport +class httpconnection(keepalive.HTTPConnection): + # must be able to send big bundle as stream. + + def send(self, data): + if isinstance(data, str): + keepalive.HTTPConnection.send(self, data) + else: + # if auth required, some data sent twice, so rewind here + data.seek(0) + for chunk in util.filechunkiter(data): + keepalive.HTTPConnection.send(self, chunk) + +class httphandler(keepalive.HTTPHandler): + def http_open(self, req): + return self.do_open(httpconnection, req) + class httprepository(remoterepository): def __init__(self, ui, path): self.caps = None @@ -86,7 +102,7 @@ proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy') proxyauthinfo = None - handler = keepalive.HTTPHandler() + handler = httphandler() if proxyurl: # proxy can be proper url or host[:port] @@ -154,6 +170,8 @@ self.caps = self.do_read('capabilities').split() except hg.RepoError: self.caps = () + self.ui.debug(_('capabilities: %s\n') % + (' '.join(self.caps or ['none']))) return self.caps capabilities = property(get_caps) @@ -165,13 +183,15 @@ raise util.Abort(_('operation not supported over http')) def do_cmd(self, cmd, **args): + data = args.pop('data', None) + headers = args.pop('headers', {}) self.ui.debug(_("sending %s command\n") % cmd) q = {"cmd": cmd} q.update(args) qs = urllib.urlencode(q) cu = "%s?%s" % (self.url, qs) try: - resp = urllib2.urlopen(cu) + resp = urllib2.urlopen(urllib2.Request(cu, data, headers)) except httplib.HTTPException, inst: self.ui.debug(_('http error while sending %s command\n') % cmd) self.ui.print_exc() @@ -249,7 +269,29 @@ return util.chunkbuffer(zgenerator(util.filechunkiter(f))) def unbundle(self, cg, heads, source): - raise util.Abort(_('operation not supported over http')) + # have to stream bundle to a temp file because we do not have + # http 1.1 chunked transfer. + + fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-') + fp = os.fdopen(fd, 'wb+') + try: + for chunk in util.filechunkiter(cg): + fp.write(chunk) + length = fp.tell() + rfp = self.do_cmd( + 'unbundle', data=fp, + headers={'content-length': length, + 'content-type': 'application/octet-stream'}, + heads=' '.join(map(hex, heads))) + try: + ret = int(rfp.readline()) + self.ui.write(rfp.read()) + return ret + finally: + rfp.close() + finally: + fp.close() + os.unlink(tempname) class httpsrepository(httprepository): pass