Mercurial > public > mercurial-scm > hg
comparison mercurial/httprepo.py @ 11587:a036f6bd1da3
protocol: unify basic http client requests
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 14 Jul 2010 16:35:51 -0500 |
parents | 34cc8b84407f |
children | 8a1f625e971d |
comparison
equal
deleted
inserted
replaced
11586:ddaaaa23bb8f | 11587:a036f6bd1da3 |
---|---|
6 # This software may be used and distributed according to the terms of the | 6 # This software may be used and distributed according to the terms of the |
7 # GNU General Public License version 2 or any later version. | 7 # GNU General Public License version 2 or any later version. |
8 | 8 |
9 from node import bin, hex, nullid | 9 from node import bin, hex, nullid |
10 from i18n import _ | 10 from i18n import _ |
11 import repo, changegroup, statichttprepo, error, url, util, pushkey | 11 import repo, changegroup, statichttprepo, error, url, util, wireproto |
12 import os, urllib, urllib2, urlparse, zlib, httplib | 12 import os, urllib, urllib2, urlparse, zlib, httplib |
13 import errno, socket | 13 import errno, socket |
14 import encoding | 14 import encoding |
15 | 15 |
16 def zgenerator(f): | 16 def zgenerator(f): |
20 yield zd.decompress(chunk) | 20 yield zd.decompress(chunk) |
21 except httplib.HTTPException: | 21 except httplib.HTTPException: |
22 raise IOError(None, _('connection ended unexpectedly')) | 22 raise IOError(None, _('connection ended unexpectedly')) |
23 yield zd.flush() | 23 yield zd.flush() |
24 | 24 |
25 class httprepository(repo.repository): | 25 class httprepository(wireproto.wirerepository): |
26 def __init__(self, ui, path): | 26 def __init__(self, ui, path): |
27 self.path = path | 27 self.path = path |
28 self.caps = None | 28 self.caps = None |
29 self.handler = None | 29 self.handler = None |
30 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path) | 30 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path) |
136 return fp.read() | 136 return fp.read() |
137 finally: | 137 finally: |
138 # if using keepalive, allow connection to be reused | 138 # if using keepalive, allow connection to be reused |
139 fp.close() | 139 fp.close() |
140 | 140 |
141 def lookup(self, key): | 141 def _call(self, cmd, **args): |
142 self.requirecap('lookup', _('look up remote revision')) | 142 return self.do_read(cmd, **args) |
143 d = self.do_cmd("lookup", key = key).read() | 143 |
144 success, data = d[:-1].split(' ', 1) | 144 def _abort(self, exception): |
145 if int(success): | 145 raise exception |
146 return bin(data) | |
147 raise error.RepoError(data) | |
148 | |
149 def heads(self): | |
150 d = self.do_read("heads") | |
151 try: | |
152 return map(bin, d[:-1].split(" ")) | |
153 except: | |
154 raise error.ResponseError(_("unexpected response:"), d) | |
155 | |
156 def branchmap(self): | |
157 d = self.do_read("branchmap") | |
158 try: | |
159 branchmap = {} | |
160 for branchpart in d.splitlines(): | |
161 branchheads = branchpart.split(' ') | |
162 branchname = urllib.unquote(branchheads[0]) | |
163 # Earlier servers (1.3.x) send branch names in (their) local | |
164 # charset. The best we can do is assume it's identical to our | |
165 # own local charset, in case it's not utf-8. | |
166 try: | |
167 branchname.decode('utf-8') | |
168 except UnicodeDecodeError: | |
169 branchname = encoding.fromlocal(branchname) | |
170 branchheads = [bin(x) for x in branchheads[1:]] | |
171 branchmap[branchname] = branchheads | |
172 return branchmap | |
173 except: | |
174 raise error.ResponseError(_("unexpected response:"), d) | |
175 | |
176 def branches(self, nodes): | |
177 n = " ".join(map(hex, nodes)) | |
178 d = self.do_read("branches", nodes=n) | |
179 try: | |
180 br = [tuple(map(bin, b.split(" "))) for b in d.splitlines()] | |
181 return br | |
182 except: | |
183 raise error.ResponseError(_("unexpected response:"), d) | |
184 | |
185 def between(self, pairs): | |
186 batch = 8 # avoid giant requests | |
187 r = [] | |
188 for i in xrange(0, len(pairs), batch): | |
189 n = " ".join(["-".join(map(hex, p)) for p in pairs[i:i + batch]]) | |
190 d = self.do_read("between", pairs=n) | |
191 try: | |
192 r += [l and map(bin, l.split(" ")) or [] | |
193 for l in d.splitlines()] | |
194 except: | |
195 raise error.ResponseError(_("unexpected response:"), d) | |
196 return r | |
197 | 146 |
198 def changegroup(self, nodes, kind): | 147 def changegroup(self, nodes, kind): |
199 n = " ".join(map(hex, nodes)) | 148 n = " ".join(map(hex, nodes)) |
200 f = self.do_cmd("changegroup", roots=n) | 149 f = self.do_cmd("changegroup", roots=n) |
201 return util.chunkbuffer(zgenerator(f)) | 150 return util.chunkbuffer(zgenerator(f)) |
257 os.unlink(tempname) | 206 os.unlink(tempname) |
258 | 207 |
259 def stream_out(self): | 208 def stream_out(self): |
260 return self.do_cmd('stream_out') | 209 return self.do_cmd('stream_out') |
261 | 210 |
262 def pushkey(self, namespace, key, old, new): | |
263 if not self.capable('pushkey'): | |
264 return False | |
265 d = self.do_cmd("pushkey", data="", # force a POST | |
266 namespace=namespace, key=key, old=old, new=new).read() | |
267 code, output = d.split('\n', 1) | |
268 try: | |
269 ret = bool(int(code)) | |
270 except ValueError, err: | |
271 raise error.ResponseError( | |
272 _('push failed (unexpected response):'), d) | |
273 for l in output.splitlines(True): | |
274 self.ui.status(_('remote: '), l) | |
275 return ret | |
276 | |
277 def listkeys(self, namespace): | |
278 if not self.capable('pushkey'): | |
279 return {} | |
280 d = self.do_cmd("listkeys", namespace=namespace).read() | |
281 r = {} | |
282 for l in d.splitlines(): | |
283 k, v = l.split('\t') | |
284 r[k.decode('string-escape')] = v.decode('string-escape') | |
285 return r | |
286 | |
287 class httpsrepository(httprepository): | 211 class httpsrepository(httprepository): |
288 def __init__(self, ui, path): | 212 def __init__(self, ui, path): |
289 if not url.has_https: | 213 if not url.has_https: |
290 raise util.Abort(_('Python support for SSL and HTTPS ' | 214 raise util.Abort(_('Python support for SSL and HTTPS ' |
291 'is not installed')) | 215 'is not installed')) |