[PATCH] Authenticating proxy support in mercurial

Michael S. Tsirkin mst at mellanox.co.il
Wed Jun 8 22:52:07 UTC 2005


Quoting r. Matt Mackall <mpm at selenic.com>:
> Subject: Re: [PATCH] Authenticating proxy support in mercurial
> 
> On Wed, Jun 08, 2005 at 08:31:04PM +0300, Michael S. Tsirkin wrote:
> > Quoting r. Jake Edge <jake at edge2.net>:
> > > Subject: Re: hg merge: TypeError
> > > >>I'm behind a proxy, could that be the problem, somehow?
> > > 
> > > ... if you are going through a proxy, that would mean that there is some 
> > > other host that you need to contact on the way out to the net ... are 
> > > you unable to do 'telnet selenic.com 80' from your localhost because of 
> > > firewalling or somesuch?  if so, i don't think hg merge is going to work 
> > > without some changes to the code ...
> > 
> > Okay, what I have here is proxy with password authentication.
> 
> Good stab at an interesting problem.
> 
> Things I'd suggest:
> 
> - sync up with the tree, quite a lot has changed since last week!

I did, the patch applies there.

> - config handling should be a property of ui, and not the repo
> - hgpaths should be handled this way too!
> 
> > diff -rup mercurial-0.5b/mercurial/hg.py mercurial-0.5b-proxy/mercurial/hg.py
> > --- mercurial-0.5b/mercurial/hg.py	2005-05-30 18:32:59.000000000 +0300
> > +++ mercurial-0.5b-proxy/mercurial/hg.py	2005-06-08 20:29:25.000000000 +0300
> > @@ -7,6 +7,8 @@
> >  
> >  import sys, struct, sha, socket, os, time, re, urllib2
> >  import urllib
> > +import urllib2
> 
> See the new demandload bits
> 
> > +import ConfigParser
> >  from mercurial import byterange, lock
> >  from mercurial.transaction import *
> >  from mercurial.revlog import *
> > @@ -844,6 +846,57 @@ class remoterepository:
> >      def __init__(self, ui, path):
> >          self.url = path
> >          self.ui = ui
> > +	pf = os.path.join(os.environ["HOME"], ".hgrc")
> 
> Use os.path.expanduser("~/.hgrc")

OK but I think I saw HOME in some other place in code.
Try to grep for it.

> > +	p = ConfigParser.SafeConfigParser()
> > +	p.read(pf)
> 
> Stick this in ui.__init__ and make it retrievable as config(). Then if
> we need to, we can demand load it.
> 
> Tell you what, I like this config file idea enough that I'll implement
> that piece of it myself. And then you can handle the proxy bit.

Good. Thanks.

> > +
> > +	if (p.has_option("http_proxy", "host")):
> > +		host = p.get("http_proxy", "host")
> > +	else:
> > +		host = None
> 
> Use get with a default instead:
> 
>     host = p.get("http_proxy", "host", None)
> 
> Then this section all gets really small.

Right.

> > +
> > +	if (p.has_option("http_proxy", "user")):
> > +		user = p.get("http_proxy", "user")
> > +	else:
> > +		user = None
> > +
> > +	if (p.has_option("http_proxy", "passwd")):
> > +		passwd = p.get("http_proxy", "passwd")
> > +	else:
> > +		passwd = None
> > +
> > +	if (p.has_option("http_proxy", "no")):
> > +		no = p.get("http_proxy", "no")
> > +		no_list = no.split(",")
> 
> Can we have a whitespace-separated list instead?

Sure - commas come from netscape background

> > +	else:
> > +		no_list = []
> > +
> > +	no_proxy = 0
> > +	for h in no_list:
> > +		if h in path:
> > +			no_proxy = 1
> 
> Might want startswith rather than in.
> 
> And maybe filter().

I'm new to python, so I'll have to read up on these constructs :). Links ?

> > +	if ("http://localhost:" in path):
> > +		no_proxy = 1
> > +
> > +	if ((no_proxy == 1) or (host == None)) :
> 
> if no_proxy or not host:
> 
> > +		os.environ["default_proxy"] = ""
> > +		os.environ["http_proxy"] = ""
> > +		os.environ["HTTP_PROXY"] = ""
> 
> This looks suspicious. Is this how urllib2 wants things?

It takes proxy values from the environment and the only
way to turn proxy access off that I found is this.

> > +		proxy_handler = urllib2.BaseHandler()
> > +	else:
> > +		proxy_handler = urllib2.ProxyHandler({"http" : "http://" + host})
> > +
> > +
> > +	if ((user != None) and (passwd != None)) :
> 
> if user and passwd:
> 
> > +		passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
> > +		passmgr.add_password(None, host, user, passwd)
> > +		authinfo = urllib2.ProxyBasicAuthHandler(passmgr)
> > +	else:
> > +		authinfo = None
> > +
> > +	opener = urllib2.build_opener(proxy_handler, authinfo)
> > +	urllib2.install_opener(opener)
> >  
> >      def do_cmd(self, cmd, **args):
> >          self.ui.debug("sending %s command\n" % cmd)
> > @@ -851,7 +904,7 @@ class remoterepository:
> >          q.update(args)
> >          qs = urllib.urlencode(q)
> >          cu = "%s?%s" % (self.url, qs)
> > -        return urllib.urlopen(cu)
> > +        return urllib2.urlopen(cu)
> >  
> >      def branches(self, nodes):
> >          n = " ".join(map(hex, nodes))
> > diff -rup mercurial-0.5b/README mercurial-0.5b-proxy/README
> > --- mercurial-0.5b/README	2005-05-29 20:23:56.000000000 +0300
> > +++ mercurial-0.5b-proxy/README	2005-06-08 20:20:20.000000000 +0300
> > @@ -90,3 +90,18 @@ Network support:
> >   foo$ echo "main http://selenic.com/hg/" >> ~/.hgpaths # one pair per line
> >   foo$ hg merge main
> >   foo$ hg co
> > +
> > +Non-transparent proxy support:
> > +
> > + To access a mercurial repository through a proxy,
> > + create a file ~/.hgrc in the following format:
> > +
> > +[http_proxy]
> > +host=myproxy:8080
> > +user=<username>
> > +passwd=<password>
> > +no=<localhost1>,<localhost2>,<localhost3>,...
> > +
> > + "user","passwd" fields are used for authenticating proxies,
> > + "no" is a comma-separated list of local host names for which
> > + proxy must be bypassed.
> 
> This stuff ought to go in doc/hg.1.txt instead. The README is the
> 1-minute introduction.
> 

OK

-- 
MST



More information about the Mercurial mailing list