Show More
@@ -10,7 +10,7 from remoterepo import * | |||||
10 | from i18n import gettext as _ |
|
10 | from i18n import gettext as _ | |
11 | from demandload import * |
|
11 | from demandload import * | |
12 | demandload(globals(), "hg os urllib urllib2 urlparse zlib util httplib") |
|
12 | demandload(globals(), "hg os urllib urllib2 urlparse zlib util httplib") | |
13 | demandload(globals(), "keepalive") |
|
13 | demandload(globals(), "keepalive tempfile socket") | |
14 |
|
14 | |||
15 | class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm): |
|
15 | class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm): | |
16 | def __init__(self, ui): |
|
16 | def __init__(self, ui): | |
@@ -69,6 +69,22 def netlocunsplit(host, port, user=None, | |||||
69 | return userpass + '@' + hostport |
|
69 | return userpass + '@' + hostport | |
70 | return hostport |
|
70 | return hostport | |
71 |
|
71 | |||
|
72 | class httpconnection(keepalive.HTTPConnection): | |||
|
73 | # must be able to send big bundle as stream. | |||
|
74 | ||||
|
75 | def send(self, data): | |||
|
76 | if isinstance(data, str): | |||
|
77 | keepalive.HTTPConnection.send(self, data) | |||
|
78 | else: | |||
|
79 | # if auth required, some data sent twice, so rewind here | |||
|
80 | data.seek(0) | |||
|
81 | for chunk in util.filechunkiter(data): | |||
|
82 | keepalive.HTTPConnection.send(self, chunk) | |||
|
83 | ||||
|
84 | class httphandler(keepalive.HTTPHandler): | |||
|
85 | def http_open(self, req): | |||
|
86 | return self.do_open(httpconnection, req) | |||
|
87 | ||||
72 | class httprepository(remoterepository): |
|
88 | class httprepository(remoterepository): | |
73 | def __init__(self, ui, path): |
|
89 | def __init__(self, ui, path): | |
74 | self.caps = None |
|
90 | self.caps = None | |
@@ -86,7 +102,7 class httprepository(remoterepository): | |||||
86 |
|
102 | |||
87 | proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy') |
|
103 | proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy') | |
88 | proxyauthinfo = None |
|
104 | proxyauthinfo = None | |
89 |
handler = |
|
105 | handler = httphandler() | |
90 |
|
106 | |||
91 | if proxyurl: |
|
107 | if proxyurl: | |
92 | # proxy can be proper url or host[:port] |
|
108 | # proxy can be proper url or host[:port] | |
@@ -154,6 +170,8 class httprepository(remoterepository): | |||||
154 | self.caps = self.do_read('capabilities').split() |
|
170 | self.caps = self.do_read('capabilities').split() | |
155 | except hg.RepoError: |
|
171 | except hg.RepoError: | |
156 | self.caps = () |
|
172 | self.caps = () | |
|
173 | self.ui.debug(_('capabilities: %s\n') % | |||
|
174 | (' '.join(self.caps or ['none']))) | |||
157 | return self.caps |
|
175 | return self.caps | |
158 |
|
176 | |||
159 | capabilities = property(get_caps) |
|
177 | capabilities = property(get_caps) | |
@@ -165,13 +183,15 class httprepository(remoterepository): | |||||
165 | raise util.Abort(_('operation not supported over http')) |
|
183 | raise util.Abort(_('operation not supported over http')) | |
166 |
|
184 | |||
167 | def do_cmd(self, cmd, **args): |
|
185 | def do_cmd(self, cmd, **args): | |
|
186 | data = args.pop('data', None) | |||
|
187 | headers = args.pop('headers', {}) | |||
168 | self.ui.debug(_("sending %s command\n") % cmd) |
|
188 | self.ui.debug(_("sending %s command\n") % cmd) | |
169 | q = {"cmd": cmd} |
|
189 | q = {"cmd": cmd} | |
170 | q.update(args) |
|
190 | q.update(args) | |
171 | qs = urllib.urlencode(q) |
|
191 | qs = urllib.urlencode(q) | |
172 | cu = "%s?%s" % (self.url, qs) |
|
192 | cu = "%s?%s" % (self.url, qs) | |
173 | try: |
|
193 | try: | |
174 | resp = urllib2.urlopen(cu) |
|
194 | resp = urllib2.urlopen(urllib2.Request(cu, data, headers)) | |
175 | except httplib.HTTPException, inst: |
|
195 | except httplib.HTTPException, inst: | |
176 | self.ui.debug(_('http error while sending %s command\n') % cmd) |
|
196 | self.ui.debug(_('http error while sending %s command\n') % cmd) | |
177 | self.ui.print_exc() |
|
197 | self.ui.print_exc() | |
@@ -249,7 +269,29 class httprepository(remoterepository): | |||||
249 | return util.chunkbuffer(zgenerator(util.filechunkiter(f))) |
|
269 | return util.chunkbuffer(zgenerator(util.filechunkiter(f))) | |
250 |
|
270 | |||
251 | def unbundle(self, cg, heads, source): |
|
271 | def unbundle(self, cg, heads, source): | |
252 | raise util.Abort(_('operation not supported over http')) |
|
272 | # have to stream bundle to a temp file because we do not have | |
|
273 | # http 1.1 chunked transfer. | |||
|
274 | ||||
|
275 | fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-') | |||
|
276 | fp = os.fdopen(fd, 'wb+') | |||
|
277 | try: | |||
|
278 | for chunk in util.filechunkiter(cg): | |||
|
279 | fp.write(chunk) | |||
|
280 | length = fp.tell() | |||
|
281 | rfp = self.do_cmd( | |||
|
282 | 'unbundle', data=fp, | |||
|
283 | headers={'content-length': length, | |||
|
284 | 'content-type': 'application/octet-stream'}, | |||
|
285 | heads=' '.join(map(hex, heads))) | |||
|
286 | try: | |||
|
287 | ret = int(rfp.readline()) | |||
|
288 | self.ui.write(rfp.read()) | |||
|
289 | return ret | |||
|
290 | finally: | |||
|
291 | rfp.close() | |||
|
292 | finally: | |||
|
293 | fp.close() | |||
|
294 | os.unlink(tempname) | |||
253 |
|
295 | |||
254 | class httpsrepository(httprepository): |
|
296 | class httpsrepository(httprepository): | |
255 | pass |
|
297 | pass |
General Comments 0
You need to be logged in to leave comments.
Login now