##// END OF EJS Templates
httprepo: factor out proxy handling
Benoit Boissinot -
r7269:95a53961 default
parent child Browse files
Show More
@@ -1,467 +1,481
1 1 # httprepo.py - HTTP repository proxy classes for mercurial
2 2 #
3 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms
7 7 # of the GNU General Public License, incorporated herein by reference.
8 8
9 9 from node import bin, hex, nullid
10 10 from i18n import _
11 11 import repo, os, urllib, urllib2, urlparse, zlib, util, httplib
12 12 import errno, keepalive, socket, changegroup, statichttprepo
13 13
14 14 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
15 15 def __init__(self, ui):
16 16 urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
17 17 self.ui = ui
18 18
19 19 def find_user_password(self, realm, authuri):
20 20 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
21 21 self, realm, authuri)
22 22 user, passwd = authinfo
23 23 if user and passwd:
24 24 return (user, passwd)
25 25
26 26 if not self.ui.interactive:
27 27 raise util.Abort(_('http authorization required'))
28 28
29 29 self.ui.write(_("http authorization required\n"))
30 30 self.ui.status(_("realm: %s\n") % realm)
31 31 if user:
32 32 self.ui.status(_("user: %s\n") % user)
33 33 else:
34 34 user = self.ui.prompt(_("user:"), default=None)
35 35
36 36 if not passwd:
37 37 passwd = self.ui.getpass()
38 38
39 39 self.add_password(realm, authuri, user, passwd)
40 40 return (user, passwd)
41 41
42 class proxyhandler(urllib2.ProxyHandler):
43 def __init__(self, ui):
44 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
45 # XXX proxyauthinfo = None
46
47 if proxyurl:
48 # proxy can be proper url or host[:port]
49 if not (proxyurl.startswith('http:') or
50 proxyurl.startswith('https:')):
51 proxyurl = 'http://' + proxyurl + '/'
52 snpqf = urlparse.urlsplit(proxyurl)
53 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
54 hpup = netlocsplit(proxynetloc)
55
56 proxyhost, proxyport, proxyuser, proxypasswd = hpup
57 if not proxyuser:
58 proxyuser = ui.config("http_proxy", "user")
59 proxypasswd = ui.config("http_proxy", "passwd")
60
61 # see if we should use a proxy for this url
62 no_list = [ "localhost", "127.0.0.1" ]
63 no_list.extend([p.lower() for
64 p in ui.configlist("http_proxy", "no")])
65 no_list.extend([p.strip().lower() for
66 p in os.getenv("no_proxy", '').split(',')
67 if p.strip()])
68 # "http_proxy.always" config is for running tests on localhost
69 if ui.configbool("http_proxy", "always"):
70 self.no_list = []
71 else:
72 self.no_list = no_list
73
74 proxyurl = urlparse.urlunsplit((
75 proxyscheme, netlocunsplit(proxyhost, proxyport,
76 proxyuser, proxypasswd or ''),
77 proxypath, proxyquery, proxyfrag))
78 proxies = {'http': proxyurl, 'https': proxyurl}
79 ui.debug(_('proxying through http://%s:%s\n') %
80 (proxyhost, proxyport))
81 else:
82 proxies = {}
83
84 # urllib2 takes proxy values from the environment and those
85 # will take precedence if found, so drop them
86 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
87 try:
88 if env in os.environ:
89 del os.environ[env]
90 except OSError:
91 pass
92
93 urllib2.ProxyHandler.__init__(self, proxies)
94 self.ui = ui
95
96 def proxy_open(self, req, proxy, type):
97 host = req.get_host().split(':')[0]
98 if host in self.no_list:
99 return None
100 return urllib2.ProxyHandler.proxy_open(self, req, proxy, type)
101
42 102 def netlocsplit(netloc):
43 103 '''split [user[:passwd]@]host[:port] into 4-tuple.'''
44 104
45 105 a = netloc.find('@')
46 106 if a == -1:
47 107 user, passwd = None, None
48 108 else:
49 109 userpass, netloc = netloc[:a], netloc[a+1:]
50 110 c = userpass.find(':')
51 111 if c == -1:
52 112 user, passwd = urllib.unquote(userpass), None
53 113 else:
54 114 user = urllib.unquote(userpass[:c])
55 115 passwd = urllib.unquote(userpass[c+1:])
56 116 c = netloc.find(':')
57 117 if c == -1:
58 118 host, port = netloc, None
59 119 else:
60 120 host, port = netloc[:c], netloc[c+1:]
61 121 return host, port, user, passwd
62 122
63 123 def netlocunsplit(host, port, user=None, passwd=None):
64 124 '''turn host, port, user, passwd into [user[:passwd]@]host[:port].'''
65 125 if port:
66 126 hostport = host + ':' + port
67 127 else:
68 128 hostport = host
69 129 if user:
70 130 if passwd:
71 131 userpass = urllib.quote(user) + ':' + urllib.quote(passwd)
72 132 else:
73 133 userpass = urllib.quote(user)
74 134 return userpass + '@' + hostport
75 135 return hostport
76 136
77 137 # work around a bug in Python < 2.4.2
78 138 # (it leaves a "\n" at the end of Proxy-authorization headers)
79 139 class request(urllib2.Request):
80 140 def add_header(self, key, val):
81 141 if key.lower() == 'proxy-authorization':
82 142 val = val.strip()
83 143 return urllib2.Request.add_header(self, key, val)
84 144
85 145 class httpsendfile(file):
86 146 def __len__(self):
87 147 return os.fstat(self.fileno()).st_size
88 148
89 149 def _gen_sendfile(connection):
90 150 def _sendfile(self, data):
91 151 # send a file
92 152 if isinstance(data, httpsendfile):
93 153 # if auth required, some data sent twice, so rewind here
94 154 data.seek(0)
95 155 for chunk in util.filechunkiter(data):
96 156 connection.send(self, chunk)
97 157 else:
98 158 connection.send(self, data)
99 159 return _sendfile
100 160
101 161 class httpconnection(keepalive.HTTPConnection):
102 162 # must be able to send big bundle as stream.
103 163 send = _gen_sendfile(keepalive.HTTPConnection)
104 164
105 165 class httphandler(keepalive.HTTPHandler):
106 166 def http_open(self, req):
107 167 return self.do_open(httpconnection, req)
108 168
109 169 def __del__(self):
110 170 self.close_all()
111 171
112 172 has_https = hasattr(urllib2, 'HTTPSHandler')
113 173 if has_https:
114 174 class httpsconnection(httplib.HTTPSConnection):
115 175 response_class = keepalive.HTTPResponse
116 176 # must be able to send big bundle as stream.
117 177 send = _gen_sendfile(httplib.HTTPSConnection)
118 178
119 179 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
120 180 def https_open(self, req):
121 181 return self.do_open(httpsconnection, req)
122 182
123 183 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
124 184 # it doesn't know about the auth type requested. This can happen if
125 185 # somebody is using BasicAuth and types a bad password.
126 186 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
127 187 def http_error_auth_reqed(self, auth_header, host, req, headers):
128 188 try:
129 189 return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
130 190 self, auth_header, host, req, headers)
131 191 except ValueError, inst:
132 192 arg = inst.args[0]
133 193 if arg.startswith("AbstractDigestAuthHandler doesn't know "):
134 194 return
135 195 raise
136 196
137 197 def zgenerator(f):
138 198 zd = zlib.decompressobj()
139 199 try:
140 200 for chunk in util.filechunkiter(f):
141 201 yield zd.decompress(chunk)
142 202 except httplib.HTTPException, inst:
143 203 raise IOError(None, _('connection ended unexpectedly'))
144 204 yield zd.flush()
145 205
146 206 _safe = ('abcdefghijklmnopqrstuvwxyz'
147 207 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
148 208 '0123456789' '_.-/')
149 209 _safeset = None
150 210 _hex = None
151 211 def quotepath(path):
152 212 '''quote the path part of a URL
153 213
154 214 This is similar to urllib.quote, but it also tries to avoid
155 215 quoting things twice (inspired by wget):
156 216
157 217 >>> quotepath('abc def')
158 218 'abc%20def'
159 219 >>> quotepath('abc%20def')
160 220 'abc%20def'
161 221 >>> quotepath('abc%20 def')
162 222 'abc%20%20def'
163 223 >>> quotepath('abc def%20')
164 224 'abc%20def%20'
165 225 >>> quotepath('abc def%2')
166 226 'abc%20def%252'
167 227 >>> quotepath('abc def%')
168 228 'abc%20def%25'
169 229 '''
170 230 global _safeset, _hex
171 231 if _safeset is None:
172 232 _safeset = util.set(_safe)
173 233 _hex = util.set('abcdefABCDEF0123456789')
174 234 l = list(path)
175 235 for i in xrange(len(l)):
176 236 c = l[i]
177 237 if c == '%' and i + 2 < len(l) and (l[i+1] in _hex and l[i+2] in _hex):
178 238 pass
179 239 elif c not in _safeset:
180 240 l[i] = '%%%02X' % ord(c)
181 241 return ''.join(l)
182 242
183 243 class httprepository(repo.repository):
184 244 def __init__(self, ui, path):
185 245 self.path = path
186 246 self.caps = None
187 247 self.handler = None
188 248 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
189 249 if query or frag:
190 250 raise util.Abort(_('unsupported URL component: "%s"') %
191 251 (query or frag))
192 252 if not urlpath:
193 253 urlpath = '/'
194 254 urlpath = quotepath(urlpath)
195 255 host, port, user, passwd = netlocsplit(netloc)
196 256
197 257 # urllib cannot handle URLs with embedded user or passwd
198 258 self._url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
199 259 urlpath, '', ''))
200 260 self.ui = ui
201 261 self.ui.debug(_('using %s\n') % self._url)
202 262
203 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
204 # XXX proxyauthinfo = None
205 263 handlers = [httphandler()]
206 264 if has_https:
207 265 handlers.append(httpshandler())
208 266
209 if proxyurl:
210 # proxy can be proper url or host[:port]
211 if not (proxyurl.startswith('http:') or
212 proxyurl.startswith('https:')):
213 proxyurl = 'http://' + proxyurl + '/'
214 snpqf = urlparse.urlsplit(proxyurl)
215 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
216 hpup = netlocsplit(proxynetloc)
217
218 proxyhost, proxyport, proxyuser, proxypasswd = hpup
219 if not proxyuser:
220 proxyuser = ui.config("http_proxy", "user")
221 proxypasswd = ui.config("http_proxy", "passwd")
222
223 # see if we should use a proxy for this url
224 no_list = [ "localhost", "127.0.0.1" ]
225 no_list.extend([p.lower() for
226 p in ui.configlist("http_proxy", "no")])
227 no_list.extend([p.strip().lower() for
228 p in os.getenv("no_proxy", '').split(',')
229 if p.strip()])
230 # "http_proxy.always" config is for running tests on localhost
231 if (not ui.configbool("http_proxy", "always") and
232 host.lower() in no_list):
233 # avoid auto-detection of proxy settings by appending
234 # a ProxyHandler with no proxies defined.
235 handlers.append(urllib2.ProxyHandler({}))
236 ui.debug(_('disabling proxy for %s\n') % host)
237 else:
238 proxyurl = urlparse.urlunsplit((
239 proxyscheme, netlocunsplit(proxyhost, proxyport,
240 proxyuser, proxypasswd or ''),
241 proxypath, proxyquery, proxyfrag))
242 handlers.append(urllib2.ProxyHandler({scheme: proxyurl}))
243 ui.debug(_('proxying through http://%s:%s\n') %
244 (proxyhost, proxyport))
245
246 # urllib2 takes proxy values from the environment and those
247 # will take precedence if found, so drop them
248 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
249 try:
250 if env in os.environ:
251 del os.environ[env]
252 except OSError:
253 pass
267 handlers.append(proxyhandler(ui))
254 268
255 269 passmgr = passwordmgr(ui)
256 270 if user:
257 271 ui.debug(_('http auth: user %s, password %s\n') %
258 272 (user, passwd and '*' * len(passwd) or 'not set'))
259 273 netloc = host
260 274 if port:
261 275 netloc += ':' + port
262 276 # Python < 2.4.3 uses only the netloc to search for a password
263 277 passmgr.add_password(None, (self._url, netloc), user, passwd or '')
264 278
265 279 handlers.extend((urllib2.HTTPBasicAuthHandler(passmgr),
266 280 httpdigestauthhandler(passmgr)))
267 281 opener = urllib2.build_opener(*handlers)
268 282
269 283 # 1.0 here is the _protocol_ version
270 284 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
271 285 opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
272 286 urllib2.install_opener(opener)
273 287
274 288 def url(self):
275 289 return self.path
276 290
277 291 # look up capabilities only when needed
278 292
279 293 def get_caps(self):
280 294 if self.caps is None:
281 295 try:
282 296 self.caps = util.set(self.do_read('capabilities').split())
283 297 except repo.RepoError:
284 298 self.caps = util.set()
285 299 self.ui.debug(_('capabilities: %s\n') %
286 300 (' '.join(self.caps or ['none'])))
287 301 return self.caps
288 302
289 303 capabilities = property(get_caps)
290 304
291 305 def lock(self):
292 306 raise util.Abort(_('operation not supported over http'))
293 307
294 308 def do_cmd(self, cmd, **args):
295 309 data = args.pop('data', None)
296 310 headers = args.pop('headers', {})
297 311 self.ui.debug(_("sending %s command\n") % cmd)
298 312 q = {"cmd": cmd}
299 313 q.update(args)
300 314 qs = '?%s' % urllib.urlencode(q)
301 315 cu = "%s%s" % (self._url, qs)
302 316 try:
303 317 if data:
304 318 self.ui.debug(_("sending %s bytes\n") % len(data))
305 319 resp = urllib2.urlopen(request(cu, data, headers))
306 320 except urllib2.HTTPError, inst:
307 321 if inst.code == 401:
308 322 raise util.Abort(_('authorization failed'))
309 323 raise
310 324 except httplib.HTTPException, inst:
311 325 self.ui.debug(_('http error while sending %s command\n') % cmd)
312 326 self.ui.print_exc()
313 327 raise IOError(None, inst)
314 328 except IndexError:
315 329 # this only happens with Python 2.3, later versions raise URLError
316 330 raise util.Abort(_('http error, possibly caused by proxy setting'))
317 331 # record the url we got redirected to
318 332 resp_url = resp.geturl()
319 333 if resp_url.endswith(qs):
320 334 resp_url = resp_url[:-len(qs)]
321 335 if self._url != resp_url:
322 336 self.ui.status(_('real URL is %s\n') % resp_url)
323 337 self._url = resp_url
324 338 try:
325 339 proto = resp.getheader('content-type')
326 340 except AttributeError:
327 341 proto = resp.headers['content-type']
328 342
329 343 # accept old "text/plain" and "application/hg-changegroup" for now
330 344 if not (proto.startswith('application/mercurial-') or
331 345 proto.startswith('text/plain') or
332 346 proto.startswith('application/hg-changegroup')):
333 347 self.ui.debug(_("Requested URL: '%s'\n") % cu)
334 348 raise repo.RepoError(_("'%s' does not appear to be an hg repository")
335 349 % self._url)
336 350
337 351 if proto.startswith('application/mercurial-'):
338 352 try:
339 353 version = proto.split('-', 1)[1]
340 354 version_info = tuple([int(n) for n in version.split('.')])
341 355 except ValueError:
342 356 raise repo.RepoError(_("'%s' sent a broken Content-Type "
343 357 "header (%s)") % (self._url, proto))
344 358 if version_info > (0, 1):
345 359 raise repo.RepoError(_("'%s' uses newer protocol %s") %
346 360 (self._url, version))
347 361
348 362 return resp
349 363
350 364 def do_read(self, cmd, **args):
351 365 fp = self.do_cmd(cmd, **args)
352 366 try:
353 367 return fp.read()
354 368 finally:
355 369 # if using keepalive, allow connection to be reused
356 370 fp.close()
357 371
358 372 def lookup(self, key):
359 373 self.requirecap('lookup', _('look up remote revision'))
360 374 d = self.do_cmd("lookup", key = key).read()
361 375 success, data = d[:-1].split(' ', 1)
362 376 if int(success):
363 377 return bin(data)
364 378 raise repo.RepoError(data)
365 379
366 380 def heads(self):
367 381 d = self.do_read("heads")
368 382 try:
369 383 return map(bin, d[:-1].split(" "))
370 384 except:
371 385 raise util.UnexpectedOutput(_("unexpected response:"), d)
372 386
373 387 def branches(self, nodes):
374 388 n = " ".join(map(hex, nodes))
375 389 d = self.do_read("branches", nodes=n)
376 390 try:
377 391 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
378 392 return br
379 393 except:
380 394 raise util.UnexpectedOutput(_("unexpected response:"), d)
381 395
382 396 def between(self, pairs):
383 397 n = " ".join(["-".join(map(hex, p)) for p in pairs])
384 398 d = self.do_read("between", pairs=n)
385 399 try:
386 400 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
387 401 return p
388 402 except:
389 403 raise util.UnexpectedOutput(_("unexpected response:"), d)
390 404
391 405 def changegroup(self, nodes, kind):
392 406 n = " ".join(map(hex, nodes))
393 407 f = self.do_cmd("changegroup", roots=n)
394 408 return util.chunkbuffer(zgenerator(f))
395 409
396 410 def changegroupsubset(self, bases, heads, source):
397 411 self.requirecap('changegroupsubset', _('look up remote changes'))
398 412 baselst = " ".join([hex(n) for n in bases])
399 413 headlst = " ".join([hex(n) for n in heads])
400 414 f = self.do_cmd("changegroupsubset", bases=baselst, heads=headlst)
401 415 return util.chunkbuffer(zgenerator(f))
402 416
403 417 def unbundle(self, cg, heads, source):
404 418 # have to stream bundle to a temp file because we do not have
405 419 # http 1.1 chunked transfer.
406 420
407 421 type = ""
408 422 types = self.capable('unbundle')
409 423 # servers older than d1b16a746db6 will send 'unbundle' as a
410 424 # boolean capability
411 425 try:
412 426 types = types.split(',')
413 427 except AttributeError:
414 428 types = [""]
415 429 if types:
416 430 for x in types:
417 431 if x in changegroup.bundletypes:
418 432 type = x
419 433 break
420 434
421 435 tempname = changegroup.writebundle(cg, None, type)
422 436 fp = httpsendfile(tempname, "rb")
423 437 try:
424 438 try:
425 439 resp = self.do_read(
426 440 'unbundle', data=fp,
427 441 headers={'Content-Type': 'application/octet-stream'},
428 442 heads=' '.join(map(hex, heads)))
429 443 resp_code, output = resp.split('\n', 1)
430 444 try:
431 445 ret = int(resp_code)
432 446 except ValueError, err:
433 447 raise util.UnexpectedOutput(
434 448 _('push failed (unexpected response):'), resp)
435 449 self.ui.write(output)
436 450 return ret
437 451 except socket.error, err:
438 452 if err[0] in (errno.ECONNRESET, errno.EPIPE):
439 453 raise util.Abort(_('push failed: %s') % err[1])
440 454 raise util.Abort(err[1])
441 455 finally:
442 456 fp.close()
443 457 os.unlink(tempname)
444 458
445 459 def stream_out(self):
446 460 return self.do_cmd('stream_out')
447 461
448 462 class httpsrepository(httprepository):
449 463 def __init__(self, ui, path):
450 464 if not has_https:
451 465 raise util.Abort(_('Python support for SSL and HTTPS '
452 466 'is not installed'))
453 467 httprepository.__init__(self, ui, path)
454 468
455 469 def instance(ui, path, create):
456 470 if create:
457 471 raise util.Abort(_('cannot create new http repository'))
458 472 try:
459 473 if path.startswith('https:'):
460 474 inst = httpsrepository(ui, path)
461 475 else:
462 476 inst = httprepository(ui, path)
463 477 inst.between([(nullid, nullid)])
464 478 return inst
465 479 except repo.RepoError:
466 480 ui.note('(falling back to static-http)\n')
467 481 return statichttprepo.instance(ui, "static-" + path, create)
@@ -1,42 +1,45
1 1 #!/bin/sh
2 2
3 3 hg init a
4 4 cd a
5 5 echo a > a
6 6 hg ci -Ama -d '1123456789 0'
7 7 hg --config server.uncompressed=True serve -p $HGPORT -d --pid-file=hg.pid
8 8 cat hg.pid >> $DAEMON_PIDS
9 9
10 10 cd ..
11 11 ("$TESTDIR/tinyproxy.py" $HGPORT1 localhost >proxy.log 2>&1 </dev/null &
12 12 echo $! > proxy.pid)
13 13 cat proxy.pid >> $DAEMON_PIDS
14 14 sleep 2
15 15
16 16 echo %% url for proxy, stream
17 17 http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone --uncompressed http://localhost:$HGPORT/ b | \
18 18 sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
19 19 cd b
20 20 hg verify
21 21 cd ..
22 22
23 23 echo %% url for proxy, pull
24 24 http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT/ b-pull
25 25 cd b-pull
26 26 hg verify
27 27 cd ..
28 28
29 29 echo %% host:port for proxy
30 30 http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ c
31 31
32 32 echo %% proxy url with user name and password
33 33 http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ d
34 34
35 35 echo %% url with user name and password
36 36 http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://user:passwd@localhost:$HGPORT/ e
37 37
38 38 echo %% bad host:port for proxy
39 39 http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
40 40
41 echo %% do not use the proxy if it is in the no list
42 http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
43
41 44 cat proxy.log | sed -e 's/^.*\] /XXX /'
42 45 exit 0
@@ -1,66 +1,74
1 1 adding a
2 2 %% url for proxy, stream
3 3 streaming all changes
4 4 XXX files to transfer, XXX bytes of data
5 5 transferred XXX bytes in XXX seconds (XXX XB/sec)
6 6 updating working directory
7 7 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
8 8 checking changesets
9 9 checking manifests
10 10 crosschecking files in changesets and manifests
11 11 checking files
12 12 1 files, 1 changesets, 1 total revisions
13 13 %% url for proxy, pull
14 14 requesting all changes
15 15 adding changesets
16 16 adding manifests
17 17 adding file changes
18 18 added 1 changesets with 1 changes to 1 files
19 19 updating working directory
20 20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 21 checking changesets
22 22 checking manifests
23 23 crosschecking files in changesets and manifests
24 24 checking files
25 25 1 files, 1 changesets, 1 total revisions
26 26 %% host:port for proxy
27 27 requesting all changes
28 28 adding changesets
29 29 adding manifests
30 30 adding file changes
31 31 added 1 changesets with 1 changes to 1 files
32 32 updating working directory
33 33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 %% proxy url with user name and password
35 35 requesting all changes
36 36 adding changesets
37 37 adding manifests
38 38 adding file changes
39 39 added 1 changesets with 1 changes to 1 files
40 40 updating working directory
41 41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 %% url with user name and password
43 43 requesting all changes
44 44 adding changesets
45 45 adding manifests
46 46 adding file changes
47 47 added 1 changesets with 1 changes to 1 files
48 48 updating working directory
49 49 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 50 %% bad host:port for proxy
51 51 abort: error: Connection refused
52 %% do not use the proxy if it is in the no list
53 requesting all changes
54 adding changesets
55 adding manifests
56 adding file changes
57 added 1 changesets with 1 changes to 1 files
58 updating working directory
59 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
52 60 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
53 61 XXX "GET http://localhost:20059/?cmd=capabilities HTTP/1.1" - -
54 62 XXX "GET http://localhost:20059/?cmd=stream_out HTTP/1.1" - -
55 63 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
56 64 XXX "GET http://localhost:20059/?cmd=heads HTTP/1.1" - -
57 65 XXX "GET http://localhost:20059/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
58 66 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
59 67 XXX "GET http://localhost:20059/?cmd=heads HTTP/1.1" - -
60 68 XXX "GET http://localhost:20059/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
61 69 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
62 70 XXX "GET http://localhost:20059/?cmd=heads HTTP/1.1" - -
63 71 XXX "GET http://localhost:20059/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
64 72 XXX "GET http://localhost:20059/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
65 73 XXX "GET http://localhost:20059/?cmd=heads HTTP/1.1" - -
66 74 XXX "GET http://localhost:20059/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
General Comments 0
You need to be logged in to leave comments. Login now