##// END OF EJS Templates
Fix same performance bug as c3654cfaa77 but for httprepo.py instead.
Eric Hopper -
r1376:524ca4a0 default
parent child Browse files
Show More
@@ -1,145 +1,135 b''
1 1 # httprepo.py - HTTP repository proxy classes for mercurial
2 2 #
3 3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from node import *
9 9 from remoterepo import *
10 10 from demandload import *
11 11 demandload(globals(), "hg os urllib urllib2 urlparse zlib")
12 12
13 13 class httprepository(remoterepository):
14 14 def __init__(self, ui, path):
15 15 # fix missing / after hostname
16 16 s = urlparse.urlsplit(path)
17 17 partial = s[2]
18 18 if not partial: partial = "/"
19 19 self.url = urlparse.urlunsplit((s[0], s[1], partial, '', ''))
20 20 self.ui = ui
21 21 no_list = [ "localhost", "127.0.0.1" ]
22 22 host = ui.config("http_proxy", "host")
23 23 if host is None:
24 24 host = os.environ.get("http_proxy")
25 25 if host and host.startswith('http://'):
26 26 host = host[7:]
27 27 user = ui.config("http_proxy", "user")
28 28 passwd = ui.config("http_proxy", "passwd")
29 29 no = ui.config("http_proxy", "no")
30 30 if no is None:
31 31 no = os.environ.get("no_proxy")
32 32 if no:
33 33 no_list = no_list + no.split(",")
34 34
35 35 no_proxy = 0
36 36 for h in no_list:
37 37 if (path.startswith("http://" + h + "/") or
38 38 path.startswith("http://" + h + ":") or
39 39 path == "http://" + h):
40 40 no_proxy = 1
41 41
42 42 # Note: urllib2 takes proxy values from the environment and those will
43 43 # take precedence
44 44 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
45 45 try:
46 46 if os.environ.has_key(env):
47 47 del os.environ[env]
48 48 except OSError:
49 49 pass
50 50
51 51 proxy_handler = urllib2.BaseHandler()
52 52 if host and not no_proxy:
53 53 proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host})
54 54
55 55 authinfo = None
56 56 if user and passwd:
57 57 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
58 58 passmgr.add_password(None, host, user, passwd)
59 59 authinfo = urllib2.ProxyBasicAuthHandler(passmgr)
60 60
61 61 opener = urllib2.build_opener(proxy_handler, authinfo)
62 62 # 1.0 here is the _protocol_ version
63 63 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
64 64 urllib2.install_opener(opener)
65 65
66 66 def dev(self):
67 67 return -1
68 68
69 69 def do_cmd(self, cmd, **args):
70 70 self.ui.debug("sending %s command\n" % cmd)
71 71 q = {"cmd": cmd}
72 72 q.update(args)
73 73 qs = urllib.urlencode(q)
74 74 cu = "%s?%s" % (self.url, qs)
75 75 resp = urllib2.urlopen(cu)
76 76 proto = resp.headers['content-type']
77 77
78 78 # accept old "text/plain" and "application/hg-changegroup" for now
79 79 if not proto.startswith('application/mercurial') and \
80 80 not proto.startswith('text/plain') and \
81 81 not proto.startswith('application/hg-changegroup'):
82 82 raise hg.RepoError("'%s' does not appear to be an hg repository" %
83 83 self.url)
84 84
85 85 if proto.startswith('application/mercurial'):
86 86 version = proto[22:]
87 87 if float(version) > 0.1:
88 88 raise hg.RepoError("'%s' uses newer protocol %s" %
89 89 (self.url, version))
90 90
91 91 return resp
92 92
93 93 def heads(self):
94 94 d = self.do_cmd("heads").read()
95 95 try:
96 96 return map(bin, d[:-1].split(" "))
97 97 except:
98 98 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
99 99 raise
100 100
101 101 def branches(self, nodes):
102 102 n = " ".join(map(hex, nodes))
103 103 d = self.do_cmd("branches", nodes=n).read()
104 104 try:
105 105 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
106 106 return br
107 107 except:
108 108 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
109 109 raise
110 110
111 111 def between(self, pairs):
112 112 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
113 113 d = self.do_cmd("between", pairs=n).read()
114 114 try:
115 115 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
116 116 return p
117 117 except:
118 118 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
119 119 raise
120 120
121 121 def changegroup(self, nodes):
122 122 n = " ".join(map(hex, nodes))
123 123 f = self.do_cmd("changegroup", roots=n)
124 124 bytes = 0
125 125
126 class zread:
127 def __init__(self, f):
128 self.zd = zlib.decompressobj()
129 self.f = f
130 self.buf = ""
131 def read(self, l):
132 while l > len(self.buf):
133 r = self.f.read(4096)
134 if r:
135 self.buf += self.zd.decompress(r)
136 else:
137 self.buf += self.zd.flush()
138 break
139 d, self.buf = self.buf[:l], self.buf[l:]
140 return d
126 def zgenerator(f):
127 zd = zlib.decompressobj()
128 for chnk in f:
129 yield zd.decompress(chnk)
130 yield zd.flush()
141 131
142 return zread(f)
132 return util.chunkbuffer(zgenerator(util.filechunkiter(f)))
143 133
144 134 class httpsrepository(httprepository):
145 135 pass
General Comments 0
You need to be logged in to leave comments. Login now