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