##// END OF EJS Templates
merge
Marcin Kasperski -
r173:817841ec merge default
parent child Browse files
Show More
@@ -54,10 +54,21 b' import socket'
54 import os
54 import os
55 import sys
55 import sys
56
56
57 # pylint:disable=invalid-name
58
59 ###########################################################################
60 # Specific import trickery
61 ###########################################################################
62
63
57 def import_meu():
64 def import_meu():
58 """Imports and returns mercurial_extension_utils module.
65 """
59 Workaround for TortoiseHg/Win environment, where this module
66 Convoluted import of mercurial_extension_utils, which helps
60 can'b be easily put on PYTHONPATH"""
67 TortoiseHg/Win setups. This routine and it's use below
68 performs equivalent of
69 from mercurial_extension_utils import monkeypatch_method
70 but looks for some non-path directories.
71 """
61 try:
72 try:
62 import mercurial_extension_utils
73 import mercurial_extension_utils
63 except ImportError:
74 except ImportError:
@@ -86,7 +97,8 b' monkeypatch_method = meu.monkeypatch_met'
86 def import_keyring():
97 def import_keyring():
87 """
98 """
88 Importing keyring happens to be costly if wallet is slow, so we delay it
99 Importing keyring happens to be costly if wallet is slow, so we delay it
89 until really needed.
100 until it is really needed. The routine below also works around various
101 demandimport-related problems.
90 """
102 """
91 if 'keyring' in sys.modules:
103 if 'keyring' in sys.modules:
92 return sys.modules['keyring']
104 return sys.modules['keyring']
@@ -116,6 +128,8 b' def import_keyring():'
116 ]:
128 ]:
117 if blocked_module not in demandimport.ignore:
129 if blocked_module not in demandimport.ignore:
118 demandimport.ignore.append(blocked_module)
130 demandimport.ignore.append(blocked_module)
131
132 # Various attempts to define is_demandimport_enabled
119 try:
133 try:
120 is_demandimport_enabled = demandimport.isenabled
134 is_demandimport_enabled = demandimport.isenabled
121 except AttributeError:
135 except AttributeError:
@@ -124,6 +138,7 b' def import_keyring():'
124 orig_demandimport = demandimport.demandimport
138 orig_demandimport = demandimport.demandimport
125 except AttributeError:
139 except AttributeError:
126 orig_demandimport = demandimport._demandimport
140 orig_demandimport = demandimport._demandimport
141
127 def is_demandimport_enabled():
142 def is_demandimport_enabled():
128 """Checks whether demandimport is enabled at the moment"""
143 """Checks whether demandimport is enabled at the moment"""
129 return __import__ == orig_demandimport
144 return __import__ == orig_demandimport
@@ -148,9 +163,12 b' def import_keyring():'
148 import keyring
163 import keyring
149 return keyring
164 return keyring
150
165
166 #################################################################
167 # Actual implementation
168 #################################################################
169
151 KEYRING_SERVICE = "Mercurial"
170 KEYRING_SERVICE = "Mercurial"
152
171
153 ############################################################
154
172
155 class PasswordStore(object):
173 class PasswordStore(object):
156 """
174 """
@@ -222,17 +240,26 b' class PasswordStore(object):'
222
240
223 password_store = PasswordStore()
241 password_store = PasswordStore()
224
242
243
244 ############################################################
245 # Tiny utils
225 ############################################################
246 ############################################################
226
247
227 def _debug(ui, msg):
248 def _debug(ui, msg):
249 """Generic debug message"""
228 ui.debug("keyring: " + msg + "\n")
250 ui.debug("keyring: " + msg + "\n")
229
251
252
230 def _debug_reply(ui, msg, url, user, pwd):
253 def _debug_reply(ui, msg, url, user, pwd):
254 """Debugging used to note info about data given"""
231 _debug(ui, "%s. Url: %s, user: %s, passwd: %s" % (
255 _debug(ui, "%s. Url: %s, user: %s, passwd: %s" % (
232 msg, url, user, pwd and '*' * len(pwd) or 'not set'))
256 msg, url, user, pwd and '*' * len(pwd) or 'not set'))
233
257
234
258
235 ############################################################
259 ############################################################
260 # Mercurial modifications
261 ############################################################
262
236
263
237 class HTTPPasswordHandler(object):
264 class HTTPPasswordHandler(object):
238 """
265 """
@@ -245,6 +272,16 b' class HTTPPasswordHandler(object):'
245 self.pwd_cache = {}
272 self.pwd_cache = {}
246 self.last_reply = None
273 self.last_reply = None
247
274
275 def _return_pwd(self, ui, msg, base_url, realm, authuri, user, req, pwd):
276 """
277 Internal helper. Saves info about auth-data obtained, preserves them in last_reply
278 and returns pair user,pwd
279 """
280 _debug_reply(ui, _(msg), base_url, user, pwd)
281 self.last_reply = dict(realm=realm, authuri=authuri,
282 user=user, req=req)
283 return user, pwd
284
248 def find_auth(self, pwmgr, realm, authuri, req):
285 def find_auth(self, pwmgr, realm, authuri, req):
249 """
286 """
250 Actual implementation of find_user_password - different
287 Actual implementation of find_user_password - different
@@ -256,9 +293,9 b' class HTTPPasswordHandler(object):'
256 # request, then the previously returned auth must have been
293 # request, then the previously returned auth must have been
257 # wrong. So we note this to force password prompt (and avoid
294 # wrong. So we note this to force password prompt (and avoid
258 # reusing bad password indifinitely).
295 # reusing bad password indifinitely).
259 after_bad_auth = (self.last_reply \
296 after_bad_auth = (self.last_reply
260 and (self.last_reply['realm'] == realm) \
297 and (self.last_reply['realm'] == realm)
261 and (self.last_reply['authuri'] == authuri) \
298 and (self.last_reply['authuri'] == authuri)
262 and (self.last_reply['req'] == req))
299 and (self.last_reply['req'] == req))
263 if after_bad_auth:
300 if after_bad_auth:
264 _debug(ui, _("Working after bad authentication, cached passwords not used %s") % str(self.last_reply))
301 _debug(ui, _("Working after bad authentication, cached passwords not used %s") % str(self.last_reply))
@@ -271,11 +308,8 b' class HTTPPasswordHandler(object):'
271 user, pwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
308 user, pwd = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
272 pwmgr, realm, authuri)
309 pwmgr, realm, authuri)
273 if user and pwd:
310 if user and pwd:
274 _debug_reply(ui, _("Auth data found in repository URL"),
311 return self._return_pwd(ui, "Auth data present in repository URL", base_url,
275 base_url, user, pwd)
312 realm, authuri, user, req, pwd)
276 self.last_reply = dict(
277 realm=realm, authuri=authuri, user=user,req=req)
278 return user, pwd
279
313
280 # Loading .hg/hgrc [auth] section contents. If prefix is given,
314 # Loading .hg/hgrc [auth] section contents. If prefix is given,
281 # it will be used as a key to lookup password in the keyring.
315 # it will be used as a key to lookup password in the keyring.
@@ -292,10 +326,8 b' class HTTPPasswordHandler(object):'
292 cached_auth = self.pwd_cache.get(cache_key)
326 cached_auth = self.pwd_cache.get(cache_key)
293 if cached_auth:
327 if cached_auth:
294 user, pwd = cached_auth
328 user, pwd = cached_auth
295 _debug_reply(ui, _("Cached auth data found"),
329 return self._return_pwd(ui, "Cached auth data found", base_url,
296 base_url, user, pwd)
330 realm, authuri, user, req, pwd)
297 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
298 return user, pwd
299
331
300 if auth_user:
332 if auth_user:
301 if user and (user != auth_user):
333 if user and (user != auth_user):
@@ -303,10 +335,8 b' class HTTPPasswordHandler(object):'
303 user = auth_user
335 user = auth_user
304 if pwd:
336 if pwd:
305 self.pwd_cache[cache_key] = user, pwd
337 self.pwd_cache[cache_key] = user, pwd
306 _debug_reply(ui, _("Auth data set in .hg/hgrc"),
338 return self._return_pwd(ui, "Auth data set in .hg/hgrc", base_url,
307 base_url, user, pwd)
339 realm, authuri, user, req, pwd)
308 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
309 return user, pwd
310 else:
340 else:
311 _debug(ui, _("Username found in .hg/hgrc: %s") % user)
341 _debug(ui, _("Username found in .hg/hgrc: %s") % user)
312
342
@@ -318,10 +348,8 b' class HTTPPasswordHandler(object):'
318 pwd = password_store.get_http_password(keyring_url, user)
348 pwd = password_store.get_http_password(keyring_url, user)
319 if pwd:
349 if pwd:
320 self.pwd_cache[cache_key] = user, pwd
350 self.pwd_cache[cache_key] = user, pwd
321 _debug_reply(ui, _("Keyring password found"),
351 return self._return_pwd(ui, "Password found in keyring", base_url,
322 base_url, user, pwd)
352 realm, authuri, user, req, pwd)
323 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
324 return user, pwd
325 else:
353 else:
326 _debug(ui, _("Password not present in the keyring"))
354 _debug(ui, _("Password not present in the keyring"))
327
355
@@ -354,10 +382,8 b' class HTTPPasswordHandler(object):'
354 # Saving password to the memory cache
382 # Saving password to the memory cache
355 self.pwd_cache[cache_key] = user, pwd
383 self.pwd_cache[cache_key] = user, pwd
356
384
357 _debug_reply(ui, _("Manually entered password"),
385 return self._return_pwd(ui, "Manually entered password", base_url,
358 base_url, user, pwd)
386 realm, authuri, user, req, pwd)
359 self.last_reply = dict(realm=realm,authuri=authuri,user=user,req=req)
360 return user, pwd
361
387
362 def load_hgrc_auth(self, ui, base_url, user):
388 def load_hgrc_auth(self, ui, base_url, user):
363 """
389 """
@@ -367,11 +393,9 b' class HTTPPasswordHandler(object):'
367 element can be None)
393 element can be None)
368 """
394 """
369 # Theoretically 3 lines below should do:
395 # Theoretically 3 lines below should do:
370
371 #auth_token = self.readauthtoken(base_url)
396 # auth_token = self.readauthtoken(base_url)
372 #if auth_token:
397 # if auth_token:
373 # user, pwd = auth.get('username'), auth.get('password')
398 # user, pwd = auth.get('username'), auth.get('password')
374
375 # Unfortunately they do not work, readauthtoken always return
399 # Unfortunately they do not work, readauthtoken always return
376 # None. Why? Because ui (self.ui of passwordmgr) describes the
400 # None. Why? Because ui (self.ui of passwordmgr) describes the
377 # *remote* repository, so does *not* contain any option from
401 # *remote* repository, so does *not* contain any option from
@@ -445,6 +469,9 b' class HTTPPasswordHandler(object):'
445 parsed_url.path)
469 parsed_url.path)
446
470
447 ############################################################
471 ############################################################
472 # Monkeypatching
473 ############################################################
474
448
475
449 @monkeypatch_method(passwordmgr)
476 @monkeypatch_method(passwordmgr)
450 def find_user_password(self, realm, authuri):
477 def find_user_password(self, realm, authuri):
@@ -466,6 +493,7 b' def find_user_password(self, realm, auth'
466
493
467 return self._pwd_handler.find_auth(self, realm, authuri, req)
494 return self._pwd_handler.find_auth(self, realm, authuri, req)
468
495
496
469 @monkeypatch_method(urllib2.AbstractBasicAuthHandler, "http_error_auth_reqed")
497 @monkeypatch_method(urllib2.AbstractBasicAuthHandler, "http_error_auth_reqed")
470 def basic_http_error_auth_reqed(self, authreq, host, req, headers):
498 def basic_http_error_auth_reqed(self, authreq, host, req, headers):
471 self.passwd._http_req = req
499 self.passwd._http_req = req
@@ -474,6 +502,7 b' def basic_http_error_auth_reqed(self, au'
474 finally:
502 finally:
475 self.passwd._http_req = None
503 self.passwd._http_req = None
476
504
505
477 @monkeypatch_method(urllib2.AbstractDigestAuthHandler, "http_error_auth_reqed")
506 @monkeypatch_method(urllib2.AbstractDigestAuthHandler, "http_error_auth_reqed")
478 def digest_http_error_auth_reqed(self, authreq, host, req, headers):
507 def digest_http_error_auth_reqed(self, authreq, host, req, headers):
479 self.passwd._http_req = req
508 self.passwd._http_req = req
@@ -483,6 +512,9 b' def digest_http_error_auth_reqed(self, a'
483 self.passwd._http_req = None
512 self.passwd._http_req = None
484
513
485 ############################################################
514 ############################################################
515 # SMTP support
516 ############################################################
517
486
518
487 def try_smtp_login(ui, smtp_obj, username, password):
519 def try_smtp_login(ui, smtp_obj, username, password):
488 """
520 """
@@ -511,6 +543,7 b' def try_smtp_login(ui, smtp_obj, usernam'
511 else:
543 else:
512 raise util.Abort(inst)
544 raise util.Abort(inst)
513
545
546
514 def keyring_supported_smtp(ui, username):
547 def keyring_supported_smtp(ui, username):
515 """
548 """
516 keyring-integrated replacement for mercurial.mail._smtp
549 keyring-integrated replacement for mercurial.mail._smtp
@@ -590,8 +623,9 b' def keyring_supported_smtp(ui, username)'
590 return send
623 return send
591
624
592 ############################################################
625 ############################################################
626 # SMTP monkeypatching
627 ############################################################
593
628
594 orig_smtp = mail._smtp
595
629
596 @monkeypatch_method(mail)
630 @monkeypatch_method(mail)
597 def _smtp(ui):
631 def _smtp(ui):
@@ -608,4 +642,4 b' def _smtp(ui):'
608 if username and not password:
642 if username and not password:
609 return keyring_supported_smtp(ui, username)
643 return keyring_supported_smtp(ui, username)
610 else:
644 else:
611 return orig_smtp(ui)
645 return _smtp.orig(ui)
General Comments 0
You need to be logged in to leave comments. Login now