comparison mercurial/httprepo.py @ 1089:142b5d5ec9cc

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