Show More
@@ -262,7 +262,9 b' Supported arguments:' | |||||
262 | Optional. Username to authenticate with. If not given, and the |
|
262 | Optional. Username to authenticate with. If not given, and the | |
263 | remote site requires basic or digest authentication, the user will |
|
263 | remote site requires basic or digest authentication, the user will | |
264 | be prompted for it. Environment variables are expanded in the |
|
264 | be prompted for it. Environment variables are expanded in the | |
265 | username letting you do ``foo.username = $USER``. |
|
265 | username letting you do ``foo.username = $USER``. If the URI | |
|
266 | includes a username, only ``[auth]`` entries with a matching | |||
|
267 | username or without a username will be considered. | |||
266 |
|
268 | |||
267 | ``password`` |
|
269 | ``password`` | |
268 | Optional. Password to authenticate with. If not given, and the |
|
270 | Optional. Password to authenticate with. If not given, and the |
@@ -72,10 +72,19 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) | |||
75 | scheme, hostpath = uri.split('://', 1) |
|
79 | scheme, hostpath = uri.split('://', 1) | |
|
80 | bestuser = None | |||
76 | bestlen = 0 |
|
81 | bestlen = 0 | |
77 | bestauth = None |
|
82 | bestauth = None | |
78 | for group, auth in config.iteritems(): |
|
83 | for group, auth in config.iteritems(): | |
|
84 | if user and user != auth.get('username', user): | |||
|
85 | # If a username was set in the URI, the entry username | |||
|
86 | # must either match it or be unset | |||
|
87 | continue | |||
79 | prefix = auth.get('prefix') |
|
88 | prefix = auth.get('prefix') | |
80 | if not prefix: |
|
89 | if not prefix: | |
81 | continue |
|
90 | continue | |
@@ -85,9 +94,14 b' def readauthforuri(ui, uri):' | |||||
85 | else: |
|
94 | else: | |
86 | schemes = (auth.get('schemes') or 'https').split() |
|
95 | schemes = (auth.get('schemes') or 'https').split() | |
87 | if (prefix == '*' or hostpath.startswith(prefix)) and \ |
|
96 | if (prefix == '*' or hostpath.startswith(prefix)) and \ | |
88 |
len(prefix) > bestlen and |
|
97 | (len(prefix) > bestlen or (len(prefix) == bestlen and \ | |
|
98 | not bestuser and 'username' in auth)) \ | |||
|
99 | and scheme in schemes: | |||
89 | bestlen = len(prefix) |
|
100 | bestlen = len(prefix) | |
90 | bestauth = group, auth |
|
101 | bestauth = group, auth | |
|
102 | bestuser = auth.get('username') | |||
|
103 | if user and not bestuser: | |||
|
104 | auth['username'] = user | |||
91 | return bestauth |
|
105 | return bestauth | |
92 |
|
106 | |||
93 | # Mercurial (at least until we can remove the old codepath) requires |
|
107 | # Mercurial (at least until we can remove the old codepath) requires |
@@ -25,7 +25,7 b' class passwordmgr(urllib2.HTTPPasswordMg' | |||||
25 | self._writedebug(user, passwd) |
|
25 | self._writedebug(user, passwd) | |
26 | return (user, passwd) |
|
26 | return (user, passwd) | |
27 |
|
27 | |||
28 | if not user: |
|
28 | if not user or not passwd: | |
29 | res = httpconnectionmod.readauthforuri(self.ui, authuri) |
|
29 | res = httpconnectionmod.readauthforuri(self.ui, authuri) | |
30 | if res: |
|
30 | if res: | |
31 | group, auth = res |
|
31 | group, auth = res |
@@ -1,5 +1,5 b'' | |||||
1 | from mercurial import demandimport; demandimport.enable() |
|
1 | from mercurial import demandimport; demandimport.enable() | |
2 | from mercurial import ui |
|
2 | from mercurial import ui, util | |
3 | from mercurial import url |
|
3 | from mercurial import url | |
4 | from mercurial.error import Abort |
|
4 | from mercurial.error import Abort | |
5 |
|
5 | |||
@@ -19,13 +19,16 b' def dumpdict(dict):' | |||||
19 | return '{' + ', '.join(['%s: %s' % (k, dict[k]) |
|
19 | return '{' + ', '.join(['%s: %s' % (k, dict[k]) | |
20 | for k in sorted(dict.iterkeys())]) + '}' |
|
20 | for k in sorted(dict.iterkeys())]) + '}' | |
21 |
|
21 | |||
22 | def test(auth): |
|
22 | def test(auth, urls=None): | |
23 | print 'CFG:', dumpdict(auth) |
|
23 | print 'CFG:', dumpdict(auth) | |
24 | prefixes = set() |
|
24 | prefixes = set() | |
25 | for k in auth: |
|
25 | for k in auth: | |
26 | prefixes.add(k.split('.', 1)[0]) |
|
26 | prefixes.add(k.split('.', 1)[0]) | |
27 | for p in prefixes: |
|
27 | for p in prefixes: | |
28 |
|
|
28 | for name in ('.username', '.password'): | |
|
29 | if (p + name) not in auth: | |||
|
30 | auth[p + name] = p | |||
|
31 | auth = dict((k, v) for k, v in auth.iteritems() if v is not None) | |||
29 |
|
32 | |||
30 | ui = writeauth(auth) |
|
33 | ui = writeauth(auth) | |
31 |
|
34 | |||
@@ -33,16 +36,26 b' def test(auth):' | |||||
33 | print 'URI:', uri |
|
36 | print 'URI:', uri | |
34 | try: |
|
37 | try: | |
35 | pm = url.passwordmgr(ui) |
|
38 | pm = url.passwordmgr(ui) | |
|
39 | authinfo = util.url(uri).authinfo()[1] | |||
|
40 | if authinfo is not None: | |||
|
41 | pm.add_password(*authinfo) | |||
36 | print ' ', pm.find_user_password('test', uri) |
|
42 | print ' ', pm.find_user_password('test', uri) | |
37 | except Abort, e: |
|
43 | except Abort, e: | |
38 | print 'abort' |
|
44 | print 'abort' | |
39 |
|
45 | |||
40 | _test('http://example.org/foo') |
|
46 | if not urls: | |
41 | _test('http://example.org/foo/bar') |
|
47 | urls = [ | |
42 |
|
|
48 | 'http://example.org/foo', | |
43 |
|
|
49 | 'http://example.org/foo/bar', | |
44 |
|
|
50 | 'http://example.org/bar', | |
45 |
|
|
51 | 'https://example.org/foo', | |
|
52 | 'https://example.org/foo/bar', | |||
|
53 | 'https://example.org/bar', | |||
|
54 | 'https://x@example.org/bar', | |||
|
55 | 'https://y@example.org/bar', | |||
|
56 | ] | |||
|
57 | for u in urls: | |||
|
58 | _test(u) | |||
46 |
|
59 | |||
47 |
|
60 | |||
48 | print '\n*** Test in-uri schemes\n' |
|
61 | print '\n*** Test in-uri schemes\n' | |
@@ -62,3 +75,23 b" test({'x.prefix': 'http://example.org/fo" | |||||
62 | test({'x.prefix': 'http://example.org/foo', |
|
75 | test({'x.prefix': 'http://example.org/foo', | |
63 | 'y.prefix': 'http://example.org/foo/bar'}) |
|
76 | 'y.prefix': 'http://example.org/foo/bar'}) | |
64 | test({'x.prefix': '*', 'y.prefix': 'https://example.org/bar'}) |
|
77 | test({'x.prefix': '*', 'y.prefix': 'https://example.org/bar'}) | |
|
78 | ||||
|
79 | print '\n*** Test user matching\n' | |||
|
80 | test({'x.prefix': 'http://example.org/foo', | |||
|
81 | 'x.username': None, | |||
|
82 | 'x.password': 'xpassword'}, | |||
|
83 | urls=['http://y@example.org/foo']) | |||
|
84 | test({'x.prefix': 'http://example.org/foo', | |||
|
85 | 'x.username': None, | |||
|
86 | 'x.password': 'xpassword', | |||
|
87 | 'y.prefix': 'http://example.org/foo', | |||
|
88 | 'y.username': 'y', | |||
|
89 | 'y.password': 'ypassword'}, | |||
|
90 | urls=['http://y@example.org/foo']) | |||
|
91 | test({'x.prefix': 'http://example.org/foo/bar', | |||
|
92 | 'x.username': None, | |||
|
93 | 'x.password': 'xpassword', | |||
|
94 | 'y.prefix': 'http://example.org/foo', | |||
|
95 | 'y.username': 'y', | |||
|
96 | 'y.password': 'ypassword'}, | |||
|
97 | urls=['http://y@example.org/foo/bar']) |
@@ -14,6 +14,10 b' URI: https://example.org/foo/bar' | |||||
14 | abort |
|
14 | abort | |
15 | URI: https://example.org/bar |
|
15 | URI: https://example.org/bar | |
16 | abort |
|
16 | abort | |
|
17 | URI: https://x@example.org/bar | |||
|
18 | abort | |||
|
19 | URI: https://y@example.org/bar | |||
|
20 | abort | |||
17 | CFG: {x.prefix: https://example.org} |
|
21 | CFG: {x.prefix: https://example.org} | |
18 | URI: http://example.org/foo |
|
22 | URI: http://example.org/foo | |
19 | abort |
|
23 | abort | |
@@ -27,6 +31,10 b' URI: https://example.org/foo/bar' | |||||
27 | ('x', 'x') |
|
31 | ('x', 'x') | |
28 | URI: https://example.org/bar |
|
32 | URI: https://example.org/bar | |
29 | ('x', 'x') |
|
33 | ('x', 'x') | |
|
34 | URI: https://x@example.org/bar | |||
|
35 | ('x', 'x') | |||
|
36 | URI: https://y@example.org/bar | |||
|
37 | abort | |||
30 | CFG: {x.prefix: http://example.org, x.schemes: https} |
|
38 | CFG: {x.prefix: http://example.org, x.schemes: https} | |
31 | URI: http://example.org/foo |
|
39 | URI: http://example.org/foo | |
32 | ('x', 'x') |
|
40 | ('x', 'x') | |
@@ -40,6 +48,10 b' URI: https://example.org/foo/bar' | |||||
40 | abort |
|
48 | abort | |
41 | URI: https://example.org/bar |
|
49 | URI: https://example.org/bar | |
42 | abort |
|
50 | abort | |
|
51 | URI: https://x@example.org/bar | |||
|
52 | abort | |||
|
53 | URI: https://y@example.org/bar | |||
|
54 | abort | |||
43 | CFG: {x.prefix: https://example.org, x.schemes: http} |
|
55 | CFG: {x.prefix: https://example.org, x.schemes: http} | |
44 | URI: http://example.org/foo |
|
56 | URI: http://example.org/foo | |
45 | abort |
|
57 | abort | |
@@ -53,6 +65,10 b' URI: https://example.org/foo/bar' | |||||
53 | ('x', 'x') |
|
65 | ('x', 'x') | |
54 | URI: https://example.org/bar |
|
66 | URI: https://example.org/bar | |
55 | ('x', 'x') |
|
67 | ('x', 'x') | |
|
68 | URI: https://x@example.org/bar | |||
|
69 | ('x', 'x') | |||
|
70 | URI: https://y@example.org/bar | |||
|
71 | abort | |||
56 |
|
72 | |||
57 | *** Test separately configured schemes |
|
73 | *** Test separately configured schemes | |
58 |
|
74 | |||
@@ -69,6 +85,10 b' URI: https://example.org/foo/bar' | |||||
69 | abort |
|
85 | abort | |
70 | URI: https://example.org/bar |
|
86 | URI: https://example.org/bar | |
71 | abort |
|
87 | abort | |
|
88 | URI: https://x@example.org/bar | |||
|
89 | abort | |||
|
90 | URI: https://y@example.org/bar | |||
|
91 | abort | |||
72 | CFG: {x.prefix: example.org, x.schemes: https} |
|
92 | CFG: {x.prefix: example.org, x.schemes: https} | |
73 | URI: http://example.org/foo |
|
93 | URI: http://example.org/foo | |
74 | abort |
|
94 | abort | |
@@ -82,6 +102,10 b' URI: https://example.org/foo/bar' | |||||
82 | ('x', 'x') |
|
102 | ('x', 'x') | |
83 | URI: https://example.org/bar |
|
103 | URI: https://example.org/bar | |
84 | ('x', 'x') |
|
104 | ('x', 'x') | |
|
105 | URI: https://x@example.org/bar | |||
|
106 | ('x', 'x') | |||
|
107 | URI: https://y@example.org/bar | |||
|
108 | abort | |||
85 | CFG: {x.prefix: example.org, x.schemes: http https} |
|
109 | CFG: {x.prefix: example.org, x.schemes: http https} | |
86 | URI: http://example.org/foo |
|
110 | URI: http://example.org/foo | |
87 | ('x', 'x') |
|
111 | ('x', 'x') | |
@@ -95,6 +119,10 b' URI: https://example.org/foo/bar' | |||||
95 | ('x', 'x') |
|
119 | ('x', 'x') | |
96 | URI: https://example.org/bar |
|
120 | URI: https://example.org/bar | |
97 | ('x', 'x') |
|
121 | ('x', 'x') | |
|
122 | URI: https://x@example.org/bar | |||
|
123 | ('x', 'x') | |||
|
124 | URI: https://y@example.org/bar | |||
|
125 | abort | |||
98 |
|
126 | |||
99 | *** Test prefix matching |
|
127 | *** Test prefix matching | |
100 |
|
128 | |||
@@ -111,6 +139,10 b' URI: https://example.org/foo/bar' | |||||
111 | abort |
|
139 | abort | |
112 | URI: https://example.org/bar |
|
140 | URI: https://example.org/bar | |
113 | abort |
|
141 | abort | |
|
142 | URI: https://x@example.org/bar | |||
|
143 | abort | |||
|
144 | URI: https://y@example.org/bar | |||
|
145 | abort | |||
114 | CFG: {x.prefix: http://example.org/foo, y.prefix: http://example.org/foo/bar} |
|
146 | CFG: {x.prefix: http://example.org/foo, y.prefix: http://example.org/foo/bar} | |
115 | URI: http://example.org/foo |
|
147 | URI: http://example.org/foo | |
116 | ('x', 'x') |
|
148 | ('x', 'x') | |
@@ -124,6 +156,10 b' URI: https://example.org/foo/bar' | |||||
124 | abort |
|
156 | abort | |
125 | URI: https://example.org/bar |
|
157 | URI: https://example.org/bar | |
126 | abort |
|
158 | abort | |
|
159 | URI: https://x@example.org/bar | |||
|
160 | abort | |||
|
161 | URI: https://y@example.org/bar | |||
|
162 | abort | |||
127 | CFG: {x.prefix: *, y.prefix: https://example.org/bar} |
|
163 | CFG: {x.prefix: *, y.prefix: https://example.org/bar} | |
128 | URI: http://example.org/foo |
|
164 | URI: http://example.org/foo | |
129 | abort |
|
165 | abort | |
@@ -137,3 +173,19 b' URI: https://example.org/foo/bar' | |||||
137 | ('x', 'x') |
|
173 | ('x', 'x') | |
138 | URI: https://example.org/bar |
|
174 | URI: https://example.org/bar | |
139 | ('y', 'y') |
|
175 | ('y', 'y') | |
|
176 | URI: https://x@example.org/bar | |||
|
177 | ('x', 'x') | |||
|
178 | URI: https://y@example.org/bar | |||
|
179 | ('y', 'y') | |||
|
180 | ||||
|
181 | *** Test user matching | |||
|
182 | ||||
|
183 | CFG: {x.password: xpassword, x.prefix: http://example.org/foo, x.username: None} | |||
|
184 | URI: http://y@example.org/foo | |||
|
185 | ('y', 'xpassword') | |||
|
186 | CFG: {x.password: xpassword, x.prefix: http://example.org/foo, x.username: None, y.password: ypassword, y.prefix: http://example.org/foo, y.username: y} | |||
|
187 | URI: http://y@example.org/foo | |||
|
188 | ('y', 'ypassword') | |||
|
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 | |||
|
191 | ('y', 'xpassword') |
General Comments 0
You need to be logged in to leave comments.
Login now