prompt user for http authentication info
authorVadim Gelfer <vadim.gelfer@gmail.com>
Sun, 14 May 2006 17:37:17 -0700
changeset 2281 7761597b5da3
parent 2279 51bfa0fd3a33
child 2282 2efa636eb411
prompt user for http authentication info in interactive mode, mercurial now asks the user for the username and password when the server requires it. the previous behavior was to fail with an http 401. based on patch from eric jaffe <jaffe.eric@gmail.com>.
mercurial/httprepo.py
mercurial/ui.py
--- a/mercurial/httprepo.py	Sat May 13 23:00:46 2006 -0700
+++ b/mercurial/httprepo.py	Sun May 14 17:37:17 2006 -0700
@@ -11,6 +11,25 @@
 from demandload import *
 demandload(globals(), "hg os urllib urllib2 urlparse zlib util httplib")
 
+class passwordmgr(urllib2.HTTPPasswordMgr):
+    def __init__(self, ui):
+        urllib2.HTTPPasswordMgr.__init__(self)
+        self.ui = ui
+
+    def find_user_password(self, realm, authuri):
+        authinfo = urllib2.HTTPPasswordMgr.find_user_password(
+            self, realm, authuri)
+        if authinfo != (None, None):
+            return authinfo
+
+        self.ui.write(_("http authorization required\n"))
+        self.ui.status(_("realm: %s\n") % realm)
+        user = self.ui.prompt(_("user:"), default=None)
+        passwd = self.ui.getpass()
+
+        self.add_password(realm, authuri, user, passwd)
+        return (user, passwd)
+
 class httprepository(remoterepository):
     def __init__(self, ui, path):
         # fix missing / after hostname
@@ -53,13 +72,21 @@
         if host and not no_proxy:
             proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host})
 
-        authinfo = None
+        proxyauthinfo = None
         if user and passwd:
             passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
             passmgr.add_password(None, host, user, passwd)
-            authinfo = urllib2.ProxyBasicAuthHandler(passmgr)
+            proxyauthinfo = urllib2.ProxyBasicAuthHandler(passmgr)
 
-        opener = urllib2.build_opener(proxy_handler, authinfo)
+        if ui.interactive:
+            passmgr = passwordmgr(ui)
+            opener = urllib2.build_opener(
+                proxy_handler, proxyauthinfo,
+                urllib2.HTTPBasicAuthHandler(passmgr),
+                urllib2.HTTPDigestAuthHandler(passmgr))
+        else:
+            opener = urllib2.build_opener(proxy_handler, proxyauthinfo)
+
         # 1.0 here is the _protocol_ version
         opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
         urllib2.install_opener(opener)
--- a/mercurial/ui.py	Sat May 13 23:00:46 2006 -0700
+++ b/mercurial/ui.py	Sun May 14 17:37:17 2006 -0700
@@ -8,7 +8,7 @@
 import ConfigParser
 from i18n import gettext as _
 from demandload import *
-demandload(globals(), "errno os re smtplib socket sys tempfile util")
+demandload(globals(), "errno getpass os re smtplib socket sys tempfile util")
 
 class ui(object):
     def __init__(self, verbose=False, debug=False, quiet=False,
@@ -224,15 +224,18 @@
 
     def readline(self):
         return sys.stdin.readline()[:-1]
-    def prompt(self, msg, pat, default="y"):
+    def prompt(self, msg, pat=None, default="y"):
         if not self.interactive: return default
         while 1:
             self.write(msg, " ")
             r = self.readline()
-            if re.match(pat, r):
+            if not pat or re.match(pat, r):
                 return r
             else:
                 self.write(_("unrecognized response\n"))
+    def getpass(self, prompt=None, default=None):
+        if not self.interactive: return default
+        return getpass.getpass(prompt or _('password: '))
     def status(self, *msg):
         if not self.quiet: self.write(*msg)
     def warn(self, *msg):