##// 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 # but only if they have been defined prior to the current definition.
357 # but only if they have been defined prior to the current definition.
358 for alias, definition in ui.configitems('alias'):
358 for alias, definition in ui.configitems('alias'):
359 aliasdef = cmdalias(alias, definition, cmdtable)
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 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
369 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
361 if aliasdef.norepo:
370 if aliasdef.norepo:
362 commands.norepo += ' %s' % alias
371 commands.norepo += ' %s' % alias
@@ -58,7 +58,7 b' class httpsendfile(object):'
58 return self._len
58 return self._len
59
59
60 # moved here from url.py to avoid a cycle
60 # moved here from url.py to avoid a cycle
61 def readauthforuri(ui, uri):
61 def readauthforuri(ui, uri, user):
62 # Read configuration
62 # Read configuration
63 config = dict()
63 config = dict()
64 for key, val in ui.configitems('auth'):
64 for key, val in ui.configitems('auth'):
@@ -72,10 +72,6 b' def readauthforuri(ui, uri):'
72 gdict[setting] = val
72 gdict[setting] = val
73
73
74 # Find the best match
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 scheme, hostpath = uri.split('://', 1)
75 scheme, hostpath = uri.split('://', 1)
80 bestuser = None
76 bestuser = None
81 bestlen = 0
77 bestlen = 0
@@ -238,7 +234,11 b' class http2handler(urllib2.HTTPHandler, '
238 return self.do_open(HTTPConnection, req, False)
234 return self.do_open(HTTPConnection, req, False)
239
235
240 def https_open(self, req):
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 if res:
242 if res:
243 group, auth = res
243 group, auth = res
244 self.auth = auth
244 self.auth = auth
@@ -26,7 +26,7 b' class passwordmgr(urllib2.HTTPPasswordMg'
26 return (user, passwd)
26 return (user, passwd)
27
27
28 if not user or not passwd:
28 if not user or not passwd:
29 res = httpconnectionmod.readauthforuri(self.ui, authuri)
29 res = httpconnectionmod.readauthforuri(self.ui, authuri, user)
30 if res:
30 if res:
31 group, auth = res
31 group, auth = res
32 user, passwd = auth.get('username'), auth.get('password')
32 user, passwd = auth.get('username'), auth.get('password')
@@ -53,6 +53,10 b' class passwordmgr(urllib2.HTTPPasswordMg'
53 msg = _('http auth: user %s, password %s\n')
53 msg = _('http auth: user %s, password %s\n')
54 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
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 class proxyhandler(urllib2.ProxyHandler):
60 class proxyhandler(urllib2.ProxyHandler):
57 def __init__(self, ui):
61 def __init__(self, ui):
58 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
62 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
@@ -342,7 +346,11 b' if has_https:'
342 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
346 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
343
347
344 def https_open(self, req):
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 if res:
354 if res:
347 group, auth = res
355 group, auth = res
348 self.auth = auth
356 self.auth = auth
@@ -1468,6 +1468,8 b' class url(object):'
1468 path = None
1468 path = None
1469 if not self.host:
1469 if not self.host:
1470 self.host = None
1470 self.host = None
1471 # path of file:///d is /d
1472 # path of file:///d:/ is d:/, not /d:/
1471 if path and not hasdriveletter(path):
1473 if path and not hasdriveletter(path):
1472 path = '/' + path
1474 path = '/' + path
1473
1475
@@ -1587,7 +1589,9 b' class url(object):'
1587 self.user, self.passwd = user, passwd
1589 self.user, self.passwd = user, passwd
1588 if not self.user:
1590 if not self.user:
1589 return (s, None)
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 self.user, self.passwd or ''))
1595 self.user, self.passwd or ''))
1592
1596
1593 def isabs(self):
1597 def isabs(self):
@@ -1610,11 +1614,6 b' class url(object):'
1610 path = self._hostport + '/' + self.path
1614 path = self._hostport + '/' + self.path
1611 elif self.host is not None and self.path:
1615 elif self.host is not None and self.path:
1612 path = '/' + path
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 return path
1617 return path
1619 return self._origpath
1618 return self._origpath
1620
1619
@@ -1,4 +1,5 b''
1 from mercurial import demandimport; demandimport.enable()
1 from mercurial import demandimport; demandimport.enable()
2 import urllib2
2 from mercurial import ui, util
3 from mercurial import ui, util
3 from mercurial import url
4 from mercurial import url
4 from mercurial.error import Abort
5 from mercurial.error import Abort
@@ -36,10 +37,10 b' def test(auth, urls=None):'
36 print 'URI:', uri
37 print 'URI:', uri
37 try:
38 try:
38 pm = url.passwordmgr(ui)
39 pm = url.passwordmgr(ui)
39 authinfo = util.url(uri).authinfo()[1]
40 u, authinfo = util.url(uri).authinfo()
40 if authinfo is not None:
41 if authinfo is not None:
41 pm.add_password(*authinfo)
42 pm.add_password(*authinfo)
42 print ' ', pm.find_user_password('test', uri)
43 print ' ', pm.find_user_password('test', u)
43 except Abort, e:
44 except Abort, e:
44 print 'abort'
45 print 'abort'
45
46
@@ -95,3 +96,12 b" test({'x.prefix': 'http://example.org/fo"
95 'y.username': 'y',
96 'y.username': 'y',
96 'y.password': 'ypassword'},
97 'y.password': 'ypassword'},
97 urls=['http://y@example.org/foo/bar'])
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 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}
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 URI: http://y@example.org/foo/bar
190 URI: http://y@example.org/foo/bar
191 ('y', 'xpassword')
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 abort: HTTP Error 404: Not Found
110 abort: HTTP Error 404: Not Found
111 [255]
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 check error log
162 check error log
114
163
115 $ cat error.log
164 $ cat error.log
@@ -204,18 +204,32 b' def test_url():'
204 <url scheme: 'file', path: '/foo/bar/baz'>
204 <url scheme: 'file', path: '/foo/bar/baz'>
205 >>> str(u)
205 >>> str(u)
206 'file:///foo/bar/baz'
206 'file:///foo/bar/baz'
207 >>> u.localpath()
208 '/foo/bar/baz'
207
209
208 >>> u = url('file:///foo/bar/baz')
210 >>> u = url('file:///foo/bar/baz')
209 >>> u
211 >>> u
210 <url scheme: 'file', path: '/foo/bar/baz'>
212 <url scheme: 'file', path: '/foo/bar/baz'>
211 >>> str(u)
213 >>> str(u)
212 'file:///foo/bar/baz'
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 >>> u = url('file:foo/bar/baz')
226 >>> u = url('file:foo/bar/baz')
215 >>> u
227 >>> u
216 <url scheme: 'file', path: 'foo/bar/baz'>
228 <url scheme: 'file', path: 'foo/bar/baz'>
217 >>> str(u)
229 >>> str(u)
218 'file:foo/bar/baz'
230 'file:foo/bar/baz'
231 >>> u.localpath()
232 'foo/bar/baz'
219 """
233 """
220
234
221 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
235 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
General Comments 0
You need to be logged in to leave comments. Login now