##// END OF EJS Templates
merge with stable
Matt Mackall -
r15027:1e45b92f merge default
parent child Browse files
Show More
@@ -357,6 +357,15 b' def addaliases(ui, cmdtable):'
357 357 # but only if they have been defined prior to the current definition.
358 358 for alias, definition in ui.configitems('alias'):
359 359 aliasdef = cmdalias(alias, definition, cmdtable)
360
361 try:
362 olddef = cmdtable[aliasdef.cmd][0]
363 if olddef.definition == aliasdef.definition:
364 continue
365 except (KeyError, AttributeError):
366 # definition might not exist or it might not be a cmdalias
367 pass
368
360 369 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
361 370 if aliasdef.norepo:
362 371 commands.norepo += ' %s' % alias
@@ -58,7 +58,7 b' class httpsendfile(object):'
58 58 return self._len
59 59
60 60 # moved here from url.py to avoid a cycle
61 def readauthforuri(ui, uri):
61 def readauthforuri(ui, uri, user):
62 62 # Read configuration
63 63 config = dict()
64 64 for key, val in ui.configitems('auth'):
@@ -72,10 +72,6 b' def readauthforuri(ui, uri):'
72 72 gdict[setting] = val
73 73
74 74 # Find the best match
75 uri = util.url(uri)
76 user = uri.user
77 uri.user = uri.password = None
78 uri = str(uri)
79 75 scheme, hostpath = uri.split('://', 1)
80 76 bestuser = None
81 77 bestlen = 0
@@ -238,7 +234,11 b' class http2handler(urllib2.HTTPHandler, '
238 234 return self.do_open(HTTPConnection, req, False)
239 235
240 236 def https_open(self, req):
241 res = readauthforuri(self.ui, req.get_full_url())
237 # req.get_full_url() does not contain credentials and we may
238 # need them to match the certificates.
239 url = req.get_full_url()
240 user, password = self.pwmgr.find_stored_password(url)
241 res = readauthforuri(self.ui, url, user)
242 242 if res:
243 243 group, auth = res
244 244 self.auth = auth
@@ -26,7 +26,7 b' class passwordmgr(urllib2.HTTPPasswordMg'
26 26 return (user, passwd)
27 27
28 28 if not user or not passwd:
29 res = httpconnectionmod.readauthforuri(self.ui, authuri)
29 res = httpconnectionmod.readauthforuri(self.ui, authuri, user)
30 30 if res:
31 31 group, auth = res
32 32 user, passwd = auth.get('username'), auth.get('password')
@@ -53,6 +53,10 b' class passwordmgr(urllib2.HTTPPasswordMg'
53 53 msg = _('http auth: user %s, password %s\n')
54 54 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
55 55
56 def find_stored_password(self, authuri):
57 return urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
58 self, None, authuri)
59
56 60 class proxyhandler(urllib2.ProxyHandler):
57 61 def __init__(self, ui):
58 62 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
@@ -342,7 +346,11 b' if has_https:'
342 346 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
343 347
344 348 def https_open(self, req):
345 res = httpconnectionmod.readauthforuri(self.ui, req.get_full_url())
349 # req.get_full_url() does not contain credentials and we may
350 # need them to match the certificates.
351 url = req.get_full_url()
352 user, password = self.pwmgr.find_stored_password(url)
353 res = httpconnectionmod.readauthforuri(self.ui, url, user)
346 354 if res:
347 355 group, auth = res
348 356 self.auth = auth
@@ -1468,6 +1468,8 b' class url(object):'
1468 1468 path = None
1469 1469 if not self.host:
1470 1470 self.host = None
1471 # path of file:///d is /d
1472 # path of file:///d:/ is d:/, not /d:/
1471 1473 if path and not hasdriveletter(path):
1472 1474 path = '/' + path
1473 1475
@@ -1587,7 +1589,9 b' class url(object):'
1587 1589 self.user, self.passwd = user, passwd
1588 1590 if not self.user:
1589 1591 return (s, None)
1590 return (s, (None, (str(self), self.host),
1592 # authinfo[1] is passed to urllib2 password manager, and its URIs
1593 # must not contain credentials.
1594 return (s, (None, (s, self.host),
1591 1595 self.user, self.passwd or ''))
1592 1596
1593 1597 def isabs(self):
@@ -1610,11 +1614,6 b' class url(object):'
1610 1614 path = self._hostport + '/' + self.path
1611 1615 elif self.host is not None and self.path:
1612 1616 path = '/' + path
1613 # We also need to handle the case of file:///C:/, which
1614 # should return C:/, not /C:/.
1615 elif hasdriveletter(path):
1616 # Strip leading slash from paths with drive names
1617 return path[1:]
1618 1617 return path
1619 1618 return self._origpath
1620 1619
@@ -1,4 +1,5 b''
1 1 from mercurial import demandimport; demandimport.enable()
2 import urllib2
2 3 from mercurial import ui, util
3 4 from mercurial import url
4 5 from mercurial.error import Abort
@@ -36,10 +37,10 b' def test(auth, urls=None):'
36 37 print 'URI:', uri
37 38 try:
38 39 pm = url.passwordmgr(ui)
39 authinfo = util.url(uri).authinfo()[1]
40 u, authinfo = util.url(uri).authinfo()
40 41 if authinfo is not None:
41 42 pm.add_password(*authinfo)
42 print ' ', pm.find_user_password('test', uri)
43 print ' ', pm.find_user_password('test', u)
43 44 except Abort, e:
44 45 print 'abort'
45 46
@@ -95,3 +96,12 b" test({'x.prefix': 'http://example.org/fo"
95 96 'y.username': 'y',
96 97 'y.password': 'ypassword'},
97 98 urls=['http://y@example.org/foo/bar'])
99
100 def testauthinfo(fullurl, authurl):
101 print 'URIs:', fullurl, authurl
102 pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
103 pm.add_password(*util.url(fullurl).authinfo()[1])
104 print pm.find_user_password('test', authurl)
105
106 print '\n*** Test urllib2 and util.url\n'
107 testauthinfo('http://user@example.com:8080/foo', 'http://example.com:8080/foo')
@@ -189,3 +189,8 b' URI: http://y@example.org/foo'
189 189 CFG: {x.password: xpassword, x.prefix: http://example.org/foo/bar, x.username: None, y.password: ypassword, y.prefix: http://example.org/foo, y.username: y}
190 190 URI: http://y@example.org/foo/bar
191 191 ('y', 'xpassword')
192
193 *** Test urllib2 and util.url
194
195 URIs: http://user@example.com:8080/foo http://example.com:8080/foo
196 ('user', '')
@@ -110,6 +110,55 b' clone from invalid URL'
110 110 abort: HTTP Error 404: Not Found
111 111 [255]
112 112
113 test http authentication
114
115 $ cd test
116 $ cat << EOT > userpass.py
117 > import base64
118 > from mercurial.hgweb import common
119 > def perform_authentication(hgweb, req, op):
120 > auth = req.env.get('HTTP_AUTHORIZATION')
121 > if not auth:
122 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
123 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
124 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
125 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
126 > def extsetup():
127 > common.permhooks.insert(0, perform_authentication)
128 > EOT
129 $ hg --config extensions.x=userpass.py serve -p $HGPORT2 -d --pid-file=pid
130 $ cat pid >> $DAEMON_PIDS
131
132 $ hg id http://localhost:$HGPORT2/
133 abort: http authorization required
134 [255]
135 $ hg id http://user@localhost:$HGPORT2/
136 abort: http authorization required
137 [255]
138 $ hg id http://user:pass@localhost:$HGPORT2/
139 5fed3813f7f5
140 $ echo '[auth]' >> .hg/hgrc
141 $ echo 'l.schemes=http' >> .hg/hgrc
142 $ echo 'l.prefix=lo' >> .hg/hgrc
143 $ echo 'l.username=user' >> .hg/hgrc
144 $ echo 'l.password=pass' >> .hg/hgrc
145 $ hg id http://localhost:$HGPORT2/
146 5fed3813f7f5
147 $ hg id http://localhost:$HGPORT2/
148 5fed3813f7f5
149 $ hg id http://user@localhost:$HGPORT2/
150 5fed3813f7f5
151 $ hg id http://user:pass@localhost:$HGPORT2/
152 5fed3813f7f5
153 $ hg id http://user2@localhost:$HGPORT2/
154 abort: http authorization required
155 [255]
156 $ hg id http://user:pass2@localhost:$HGPORT2/
157 abort: HTTP Error 403: no
158 [255]
159
160 $ cd ..
161
113 162 check error log
114 163
115 164 $ cat error.log
@@ -204,18 +204,32 b' def test_url():'
204 204 <url scheme: 'file', path: '/foo/bar/baz'>
205 205 >>> str(u)
206 206 'file:///foo/bar/baz'
207 >>> u.localpath()
208 '/foo/bar/baz'
207 209
208 210 >>> u = url('file:///foo/bar/baz')
209 211 >>> u
210 212 <url scheme: 'file', path: '/foo/bar/baz'>
211 213 >>> str(u)
212 214 'file:///foo/bar/baz'
215 >>> u.localpath()
216 '/foo/bar/baz'
217
218 >>> u = url('file:///f:oo/bar/baz')
219 >>> u
220 <url scheme: 'file', path: 'f:oo/bar/baz'>
221 >>> str(u)
222 'file:f%3Aoo/bar/baz'
223 >>> u.localpath()
224 'f:oo/bar/baz'
213 225
214 226 >>> u = url('file:foo/bar/baz')
215 227 >>> u
216 228 <url scheme: 'file', path: 'foo/bar/baz'>
217 229 >>> str(u)
218 230 'file:foo/bar/baz'
231 >>> u.localpath()
232 'foo/bar/baz'
219 233 """
220 234
221 235 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
General Comments 0
You need to be logged in to leave comments. Login now