##// END OF EJS Templates
allow http authentication information to be specified in the configuration
Sune Foldager -
r8333:89c80c3d default
parent child Browse files
Show More
@@ -0,0 +1,61
1 from mercurial import demandimport; demandimport.enable()
2 from mercurial import ui
3 from mercurial import url
4 from mercurial.error import Abort
5
6 class myui(ui.ui):
7 def interactive(self):
8 return False
9
10 origui = myui()
11
12 def writeauth(items):
13 ui = origui.copy()
14 for name, value in items.iteritems():
15 ui.setconfig('auth', name, value)
16 return ui
17
18 def dumpdict(dict):
19 return '{' + ', '.join(['%s: %s' % (k, dict[k]) for k in sorted(dict.iterkeys())]) + '}'
20
21 def test(auth):
22 print 'CFG:', dumpdict(auth)
23 prefixes = set()
24 for k in auth:
25 prefixes.add(k.split('.', 1)[0])
26 for p in prefixes:
27 auth.update({p + '.username': p, p + '.password': p})
28
29 ui = writeauth(auth)
30
31 def _test(uri):
32 print 'URI:', uri
33 try:
34 pm = url.passwordmgr(ui)
35 print ' ', pm.find_user_password('test', uri)
36 except Abort, e:
37 print 'abort'
38
39 _test('http://example.org/foo')
40 _test('http://example.org/foo/bar')
41 _test('http://example.org/bar')
42 _test('https://example.org/foo')
43 _test('https://example.org/foo/bar')
44 _test('https://example.org/bar')
45
46
47 print '\n*** Test in-uri schemes\n'
48 test({'x.prefix': 'http://example.org'})
49 test({'x.prefix': 'https://example.org'})
50 test({'x.prefix': 'http://example.org', 'x.schemes': 'https'})
51 test({'x.prefix': 'https://example.org', 'x.schemes': 'http'})
52
53 print '\n*** Test separately configured schemes\n'
54 test({'x.prefix': 'example.org', 'x.schemes': 'http'})
55 test({'x.prefix': 'example.org', 'x.schemes': 'https'})
56 test({'x.prefix': 'example.org', 'x.schemes': 'http https'})
57
58 print '\n*** Test prefix matching\n'
59 test({'x.prefix': 'http://example.org/foo', 'y.prefix': 'http://example.org/bar'})
60 test({'x.prefix': 'http://example.org/foo', 'y.prefix': 'http://example.org/foo/bar'})
61 test({'x.prefix': '*', 'y.prefix': 'https://example.org/bar'})
@@ -0,0 +1,139
1
2 *** Test in-uri schemes
3
4 CFG: {x.prefix: http://example.org}
5 URI: http://example.org/foo
6 ('x', 'x')
7 URI: http://example.org/foo/bar
8 ('x', 'x')
9 URI: http://example.org/bar
10 ('x', 'x')
11 URI: https://example.org/foo
12 abort
13 URI: https://example.org/foo/bar
14 abort
15 URI: https://example.org/bar
16 abort
17 CFG: {x.prefix: https://example.org}
18 URI: http://example.org/foo
19 abort
20 URI: http://example.org/foo/bar
21 abort
22 URI: http://example.org/bar
23 abort
24 URI: https://example.org/foo
25 ('x', 'x')
26 URI: https://example.org/foo/bar
27 ('x', 'x')
28 URI: https://example.org/bar
29 ('x', 'x')
30 CFG: {x.prefix: http://example.org, x.schemes: https}
31 URI: http://example.org/foo
32 ('x', 'x')
33 URI: http://example.org/foo/bar
34 ('x', 'x')
35 URI: http://example.org/bar
36 ('x', 'x')
37 URI: https://example.org/foo
38 abort
39 URI: https://example.org/foo/bar
40 abort
41 URI: https://example.org/bar
42 abort
43 CFG: {x.prefix: https://example.org, x.schemes: http}
44 URI: http://example.org/foo
45 abort
46 URI: http://example.org/foo/bar
47 abort
48 URI: http://example.org/bar
49 abort
50 URI: https://example.org/foo
51 ('x', 'x')
52 URI: https://example.org/foo/bar
53 ('x', 'x')
54 URI: https://example.org/bar
55 ('x', 'x')
56
57 *** Test separately configured schemes
58
59 CFG: {x.prefix: example.org, x.schemes: http}
60 URI: http://example.org/foo
61 ('x', 'x')
62 URI: http://example.org/foo/bar
63 ('x', 'x')
64 URI: http://example.org/bar
65 ('x', 'x')
66 URI: https://example.org/foo
67 abort
68 URI: https://example.org/foo/bar
69 abort
70 URI: https://example.org/bar
71 abort
72 CFG: {x.prefix: example.org, x.schemes: https}
73 URI: http://example.org/foo
74 abort
75 URI: http://example.org/foo/bar
76 abort
77 URI: http://example.org/bar
78 abort
79 URI: https://example.org/foo
80 ('x', 'x')
81 URI: https://example.org/foo/bar
82 ('x', 'x')
83 URI: https://example.org/bar
84 ('x', 'x')
85 CFG: {x.prefix: example.org, x.schemes: http https}
86 URI: http://example.org/foo
87 ('x', 'x')
88 URI: http://example.org/foo/bar
89 ('x', 'x')
90 URI: http://example.org/bar
91 ('x', 'x')
92 URI: https://example.org/foo
93 ('x', 'x')
94 URI: https://example.org/foo/bar
95 ('x', 'x')
96 URI: https://example.org/bar
97 ('x', 'x')
98
99 *** Test prefix matching
100
101 CFG: {x.prefix: http://example.org/foo, y.prefix: http://example.org/bar}
102 URI: http://example.org/foo
103 ('x', 'x')
104 URI: http://example.org/foo/bar
105 ('x', 'x')
106 URI: http://example.org/bar
107 ('y', 'y')
108 URI: https://example.org/foo
109 abort
110 URI: https://example.org/foo/bar
111 abort
112 URI: https://example.org/bar
113 abort
114 CFG: {x.prefix: http://example.org/foo, y.prefix: http://example.org/foo/bar}
115 URI: http://example.org/foo
116 ('x', 'x')
117 URI: http://example.org/foo/bar
118 ('y', 'y')
119 URI: http://example.org/bar
120 abort
121 URI: https://example.org/foo
122 abort
123 URI: https://example.org/foo/bar
124 abort
125 URI: https://example.org/bar
126 abort
127 CFG: {x.prefix: *, y.prefix: https://example.org/bar}
128 URI: http://example.org/foo
129 abort
130 URI: http://example.org/foo/bar
131 abort
132 URI: http://example.org/bar
133 abort
134 URI: https://example.org/foo
135 ('x', 'x')
136 URI: https://example.org/foo/bar
137 ('x', 'x')
138 URI: https://example.org/bar
139 ('y', 'y')
@@ -100,6 +100,45 This section describes the different sec
100 100 Mercurial "hgrc" file, the purpose of each section, its possible
101 101 keys, and their possible values.
102 102
103 [[auth]]
104 auth:
105 Authentication credentials for HTTP authentication.
106 Each line has the following format:
107
108 <name>.<argument> = <value>
109
110 where <name> is used to group arguments into authentication entries.
111 Example:
112
113 foo.prefix = hg.intevation.org/mercurial
114 foo.username = foo
115 foo.password = bar
116 foo.schemes = http https
117
118 Supported arguments:
119
120 prefix;;
121 Either '*' or a URI prefix with or without the scheme part. The
122 authentication entry with the longest matching prefix is used
123 (where '*' matches everything and counts as a match of length 1).
124 If the prefix doesn't include a scheme, the match is performed against
125 the URI with its scheme stripped as well, and the schemes argument,
126 q.v., is then subsequently consulted.
127 username;;
128 Username to authenticate with.
129 password;;
130 Optional. Password to authenticate with. If not given the user will be
131 prompted for it.
132 schemes;;
133 Optional. Space separated list of URI schemes to use this authentication
134 entry with. Only used if the prefix doesn't include a scheme. Supported
135 schemes are http and https. They will match static-http and static-https
136 respectively, as well.
137 Default: https.
138
139 If no suitable authentication entry is found, the user is prompted for
140 credentials as usual if required by the remote.
141
103 142 [[decode]]
104 143 decode/encode::
105 144 Filters for transforming files on checkout/checkin. This would
@@ -105,24 +105,58 class passwordmgr(urllib2.HTTPPasswordMg
105 105 self, realm, authuri)
106 106 user, passwd = authinfo
107 107 if user and passwd:
108 self._writedebug(user, passwd)
108 109 return (user, passwd)
109 110
110 if not self.ui.interactive():
111 raise util.Abort(_('http authorization required'))
111 user, passwd = self._readauthtoken(authuri)
112 if not user or not passwd:
113 if not self.ui.interactive():
114 raise util.Abort(_('http authorization required'))
112 115
113 self.ui.write(_("http authorization required\n"))
114 self.ui.status(_("realm: %s\n") % realm)
115 if user:
116 self.ui.status(_("user: %s\n") % user)
117 else:
118 user = self.ui.prompt(_("user:"), default=None)
116 self.ui.write(_("http authorization required\n"))
117 self.ui.status(_("realm: %s\n") % realm)
118 if user:
119 self.ui.status(_("user: %s\n") % user)
120 else:
121 user = self.ui.prompt(_("user:"), default=None)
119 122
120 if not passwd:
121 passwd = self.ui.getpass()
123 if not passwd:
124 passwd = self.ui.getpass()
122 125
123 126 self.add_password(realm, authuri, user, passwd)
127 self._writedebug(user, passwd)
124 128 return (user, passwd)
125 129
130 def _writedebug(self, user, passwd):
131 msg = _('http auth: user %s, password %s\n')
132 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
133
134 def _readauthtoken(self, uri):
135 # Read configuration
136 config = dict()
137 for key, val in self.ui.configitems('auth'):
138 group, setting = key.split('.', 1)
139 gdict = config.setdefault(group, dict())
140 gdict[setting] = val
141
142 # Find the best match
143 scheme, hostpath = uri.split('://', 1)
144 bestlen = 0
145 bestauth = None, None
146 for auth in config.itervalues():
147 prefix = auth.get('prefix')
148 if not prefix: continue
149 p = prefix.split('://', 1)
150 if len(p) > 1:
151 schemes, prefix = [p[0]], p[1]
152 else:
153 schemes = (auth.get('schemes') or 'https').split()
154 if (prefix == '*' or hostpath.startswith(prefix)) and \
155 len(prefix) > bestlen and scheme in schemes:
156 bestlen = len(prefix)
157 bestauth = auth.get('username'), auth.get('password')
158 return bestauth
159
126 160 class proxyhandler(urllib2.ProxyHandler):
127 161 def __init__(self, ui):
128 162 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
General Comments 0
You need to be logged in to leave comments. Login now