[PATCH] allow http authentication information to be specified in the configuration (3)

Sune Foldager cryo at cyanite.org
Wed Apr 15 09:23:56 CDT 2009


I resubmit this once more with some timeless advice taken into account wrt. the documentation. Could we please come to a decision about this patch and fix whatever we think needs fixing and then push it? Note that we will always be able to add missing features along the way, such as distinguishing different URI-schemas, without changing config files (since not given a schema would then mean 'any schema' like now).

If there are any other issues, documentation or otherwise, I will be happy to address them :-).

-- 
Sune Foldager.


# HG changeset patch
# User Sune Foldager <cryo at cyanite.org>
# Date 1239804542 -7200
# Node ID e1e68246b26c7b8e1f3b046c2715dda5b0d44bab
# Parent  28a72f620cdef2883d1332a5edcc14b05224fd7b
allow http authentication information to be specified in the configuration

diff -r 28a72f620cde -r e1e68246b26c doc/hgrc.5.txt
--- a/doc/hgrc.5.txt	Tue Apr 14 18:16:04 2009 +0200
+++ b/doc/hgrc.5.txt	Wed Apr 15 16:09:02 2009 +0200
@@ -100,6 +100,32 @@
 Mercurial "hgrc" file, the purpose of each section, its possible
 keys, and their possible values.
 
+[[auth]]
+auth:
+  Authentication tokens, consisting of username-password pairs, for
+  HTTP authentication. Each line has the following format:
+
+    <host-path prefix> = <username>[:password]
+
+  where host-path prefix can be either '*' or an URI prefix without the
+  schema part. The lines are consulted when the remote server sends
+  a challenge and no credentials were provided in the URI. The line
+  with the longest matching prefix is used. The special prefix '*' can
+  be used to match against any host-path if nothing else matches.
+  
+  If no suitable line is found, the user is prompted for credentials.
+  If only the username is given, the user is prompted for a password.
+  Usernames and passwords must be escaped as in URIs.
+
+  Example:
+
+    hg.intevation.org/mercurial = foo:bar
+    hg.intevation.org/mercurial/stable = bra:ket
+
+  Here http://hg.intevation.org/mercurial/crew will be matched against
+  the first line, while http://hg.intevation.org/mercurial/stable will
+  be matched against the second.
+
 [[decode]]
 decode/encode::
   Filters for transforming files on checkout/checkin. This would
diff -r 28a72f620cde -r e1e68246b26c mercurial/url.py
--- a/mercurial/url.py	Tue Apr 14 18:16:04 2009 +0200
+++ b/mercurial/url.py	Wed Apr 15 16:09:02 2009 +0200
@@ -105,24 +105,44 @@
             self, realm, authuri)
         user, passwd = authinfo
         if user and passwd:
+            self._writedebug(user, passwd)
             return (user, passwd)
 
-        if not self.ui.interactive:
-            raise util.Abort(_('http authorization required'))
+        user, passwd = self._readauthtoken(authuri)
+        if not user or not passwd:
+            if not self.ui.interactive:
+                raise util.Abort(_('http authorization required'))
 
-        self.ui.write(_("http authorization required\n"))
-        self.ui.status(_("realm: %s\n") % realm)
-        if user:
-            self.ui.status(_("user: %s\n") % user)
-        else:
-            user = self.ui.prompt(_("user:"), default=None)
+            self.ui.write(_("http authorization required\n"))
+            self.ui.status(_("realm: %s\n") % realm)
+            if user:
+                self.ui.status(_("user: %s\n") % user)
+            else:
+                user = self.ui.prompt(_("user:"), default=None)
 
-        if not passwd:
-            passwd = self.ui.getpass()
+            if not passwd:
+                passwd = self.ui.getpass()
 
         self.add_password(realm, authuri, user, passwd)
+        self._writedebug(user, passwd)
         return (user, passwd)
 
+    def _writedebug(self, user, passwd):
+        self.ui.debug(_('http auth: user %s, password %s\n') %
+                 (user, passwd and '*' * len(passwd) or 'not set'))
+
+    def _readauthtoken(self, uri):
+        uri = uri[uri.index('://')+3:]
+        bestlen = 0
+        bestauth = None
+        for prefix, auth in self.ui.configitems('auth'):
+            if (prefix == '*' or uri.startswith(prefix)) and len(prefix) > bestlen:
+                bestlen = len(prefix)
+                bestauth = auth
+        if bestauth:
+            return netlocsplit(bestauth + '@dummy')[2:4]
+        return None, None
+
 class proxyhandler(urllib2.ProxyHandler):
     def __init__(self, ui):
         proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
@@ -285,9 +305,6 @@
     passmgr = passwordmgr(ui)
     if authinfo is not None:
         passmgr.add_password(*authinfo)
-        user, passwd = authinfo[2:4]
-        ui.debug(_('http auth: user %s, password %s\n') %
-                 (user, passwd and '*' * len(passwd) or 'not set'))
 
     handlers.extend((urllib2.HTTPBasicAuthHandler(passmgr),
                      httpdigestauthhandler(passmgr)))





More information about the Mercurial-devel mailing list