The following error occurs when I attempt to clone over http. The client machine is a SLES 10 64bit VM. The server is a SLES 10 64 bit physical machine. hg clone http://twebapp2:8110/hg/src/HG/Cardbalance/ ** unknown exception encountered, please report by visiting ** http://mercurial.selenic.com/wiki/BugTracker ** Python 2.4.2 (#1, Dec 2 2008, 00:09:07) [GCC 4.1.2 20070115 (SUSE Linux)] ** Mercurial Distributed SCM (version 1.8.1) ** Extensions loaded: Traceback (most recent call last): File "/usr/bin/hg", line 38, in ? mercurial.dispatch.run() File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 16, in run sys.exit(dispatch(sys.argv[1:])) File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 36, in dispatch return _runcatch(u, args) File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 58, in _runcatch return _dispatch(ui, args) File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 601, in _dispatch cmdpats, cmdoptions) File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 406, in runcommand ret = _runcommand(ui, options, cmd, d) File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 655, in _runcommand return checkargs() File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 609, in checkargs return cmdfunc() File "/usr/lib64/python2.4/site-packages/mercurial/dispatch.py", line 598, in <lambda> d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) File "/usr/lib64/python2.4/site-packages/mercurial/util.py", line 433, in check return func(*args, **kwargs) File "/usr/lib64/python2.4/site-packages/mercurial/commands.py", line 825, in clone branch=opts.get('branch')) File "/usr/lib64/python2.4/site-packages/mercurial/hg.py", line 221, in clone src_repo = repository(ui, source) File "/usr/lib64/python2.4/site-packages/mercurial/hg.py", line 94, in repository repo = _lookup(path).instance(ui, path, create) File "/usr/lib64/python2.4/site-packages/mercurial/httprepo.py", line 199, in instance inst.between([(nullid, nullid)]) File "/usr/lib64/python2.4/site-packages/mercurial/wireproto.py", line 68, in between d = self._call("between", pairs=n) File "/usr/lib64/python2.4/site-packages/mercurial/httprepo.py", line 137, in _call fp = self._callstream(cmd, **args) File "/usr/lib64/python2.4/site-packages/mercurial/httprepo.py", line 88, in _callstream resp = self.urlopener.open(req) File "/usr/lib64/python2.4/urllib2.py", line 364, in open response = meth(req, response) File "/usr/lib64/python2.4/urllib2.py", line 471, in http_response response = self.parent.error( File "/usr/lib64/python2.4/urllib2.py", line 396, in error result = self._call_chain(*args) File "/usr/lib64/python2.4/urllib2.py", line 337, in _call_chain result = func(*args) File "/usr/lib64/python2.4/urllib2.py", line 741, in http_error_401 host, req, headers) File "/usr/lib64/python2.4/site-packages/mercurial/url.py", line 691, in http_error_auth_reqed return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed( File "/usr/lib64/python2.4/urllib2.py", line 720, in http_error_auth_reqed return self.retry_http_basic_auth(host, req, realm) File "/usr/lib64/python2.4/urllib2.py", line 723, in retry_http_basic_auth user,pw = self.passwd.find_user_password(realm, host) File "/usr/lib64/python2.4/site-packages/mercurial/url.py", line 158, in find_user_password res = readauthforuri(self.ui, authuri) File "/usr/lib64/python2.4/site-packages/mercurial/url.py", line 88, in readauthforuri scheme, hostpath = uri.split('://', 1) ValueError: need more than 1 value to unpack
Mercurial shouldn't crash, but it crashes because it somehow ended up with an invalid url when the server requested authentication. How is your server setup? Are you using simple basic authentication, or do you have some redirects or rewrites or evil firewalls? Does it work if you clone directly from the server?
I wonder if for some reason this is a python issue, more than a mercurial issue. I just noticed on the server i try it on, mercurial 1.8.1 is installed and python 2.4. On my laptop, I have mercurial 1.8.1 and python 2.6. The URL does not do a redirect. The only redirect I think that might be possible is appending our internal suffix. If I clone using SSH and the file system path, it does work. The server is a simple hgwebdir implementation, using basic authentication over LDAP at the apache level. There are no redirects at the apache level either. This is my apache config, slightly obfuscated: <Location "/hg"> AuthType Basic AuthName "Mercurial" AuthBasicProvider ldap AuthzLDAPAuthoritative on AuthLDAPURL "my-valid-ldap-url-goes-here" Require valid-user PythonPath "sys.path + [ '/apps/bin/mercurial' ]" #PythonDebug On #Uncomment this ligne if you got a problem and need debug information SetHandler mod_python PythonHandler modpython_gateway::handler PythonOption SCRIPT_NAME /hg PythonOption wsgi.application hgwebdir::test </Location> and my python script that serves it def make_web_app(): return hgwebdir("/apps/bin/mercurial/hgweb.config") def test(environ, start_response): toto = wsgiapplication(make_web_app) return toto (environ, start_response)
Does it work from your laptop with 2.6? Basic auth works fine for me with 2.4.3 on the client side. I would try to add a 'print uri' in url.py before/at line 88 and see if that gave a hint.
I did that, I get the hostname:port without protocol, which is likely why the code is failing. There's something else weird. I think in this environment in particular, this code is doing something different. I applied the change to my local environment as well, and it didn't execute that code. authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password( self, realm, authuri) user, passwd = authinfo if user and passwd: self._writedebug(user, passwd) return (user, passwd) if not user: res = readauthforuri(self.ui, authuri) if res: group, auth = res user, passwd = auth.get('username'), auth.get('password') self.ui.debug("using auth.%s.* for authentication\n" % group) if not user or not passwd: it skipped by the call for readauthforuri.
related: issue2070
Still occurs with 2.0-rc on python 2.4.1 (Debian sarge) with any host requiring authentication, with clone, pull or id: hg id http://foo.example.com/restricted ** unknown exception encountered, please report by visiting ** http://mercurial.selenic.com/wiki/BugTracker ** Python 2.4.1 (#2, Oct 18 2006, 20:58:01) [GCC 3.3.5 (Debian 1:3.3.5-13)] ** Mercurial Distributed SCM (version 89c80c3dc584) ** Extensions loaded: foo, mq, patchbomb, convert, transplant, fetch, churn, keyword, nearest, inout, rebase, relink Traceback (most recent call last): File "./hg", line 38, in ? mercurial.dispatch.run() File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 27, in run sys.exit(dispatch(request(sys.argv[1:]))) File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 64, in dispatch return _runcatch(req) File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 87, in _runcatch return _dispatch(req) File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 684, in _dispatch cmdpats, cmdoptions) File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 466, in runcommand ret = _runcommand(ui, options, cmd, d) File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 738, in _runcommand return checkargs() File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 692, in checkargs return cmdfunc() File "/home/thomas/hg/repos/tah/mercurial/dispatch.py", line 681, in <lambda> d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) File "/home/thomas/hg/repos/tah/mercurial/util.py", line 444, in check return func(*args, **kwargs) File "/home/thomas/hg/repos/tah/mercurial/extensions.py", line 138, in wrap return util.checksignature(wrapper)( File "/home/thomas/hg/repos/tah/mercurial/util.py", line 444, in check return func(*args, **kwargs) File "/home/thomas/hg/repos/tah/hgext/mq.py", line 3231, in mqcommand return orig(ui, repo, *args, **kwargs) File "/home/thomas/hg/repos/tah/mercurial/util.py", line 444, in check return func(*args, **kwargs) File "/home/thomas/hg/repos/tah/mercurial/commands.py", line 3259, in identify repo = hg.peer(ui, {}, source) File "/home/thomas/hg/repos/tah/mercurial/hg.py", line 104, in peer return repository(rui, path, create) File "/home/thomas/hg/repos/tah/mercurial/hg.py", line 93, in repository repo = _peerlookup(path).instance(ui, path, create) File "/home/thomas/hg/repos/tah/mercurial/httprepo.py", line 236, in instance inst._fetchcaps() File "/home/thomas/hg/repos/tah/mercurial/httprepo.py", line 57, in _fetchcaps self.caps = set(self._call('capabilities').split()) File "/home/thomas/hg/repos/tah/mercurial/httprepo.py", line 169, in _call fp = self._callstream(cmd, **args) File "/home/thomas/hg/repos/tah/mercurial/httprepo.py", line 117, in _callstream resp = self.urlopener.open(req) File "/usr/lib/python2.4/urllib2.py", line 364, in open response = meth(req, response) File "/usr/lib/python2.4/urllib2.py", line 471, in http_response response = self.parent.error( File "/usr/lib/python2.4/urllib2.py", line 396, in error result = self._call_chain(*args) File "/usr/lib/python2.4/urllib2.py", line 337, in _call_chain result = func(*args) File "/usr/lib/python2.4/urllib2.py", line 741, in http_error_401 host, req, headers) File "/home/thomas/hg/repos/tah/mercurial/url.py", line 430, in http_error_auth_reqed return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed( File "/usr/lib/python2.4/urllib2.py", line 720, in http_error_auth_reqed return self.retry_http_basic_auth(host, req, realm) File "/usr/lib/python2.4/urllib2.py", line 723, in retry_http_basic_auth user,pw = self.passwd.find_user_password(realm, host) File "/home/thomas/hg/repos/tah/mercurial/url.py", line 30, in find_user_password res = httpconnectionmod.readauthforuri(self.ui, authuri, user) File "/home/thomas/hg/repos/tah/mercurial/httpconnection.py", line 73, in readauthforuri scheme, hostpath = uri.split('://', 1) ValueError: need more than 1 value to unpack uri in readauthforuri is 'foo.example.com' The parameters of httpbasicauthhandler.http_error_auth_reqed() are: 'www-authenticate', 'foo.example.com', <mercurial.url._request instance at 0xb7acb66c>, <httplib.HTTPMessage instance at 0xb79f5c4c> So it already is the hostname instead of the URI at this point. With Python 2.6 uri is 'http://foo.example.com/restricted?cmd=capabilities' and I get asked for username/password. test-http.t.err detects this error since f32a2989ff58.
** Python 2.4.1 (#2, Oct 18 2006, 20:58:01) [GCC 3.3.5 (Debian 1:3.3.5-13)] ** Mercurial Distributed SCM (version 89c80c3dc584) That's hg build is from 2009. 2.0-rc actually doesn't run on Python 2.4 at all due to a try/except/finally sneaking. Once that compile issue is fixed, test-http.t passes with Python 2.4.3.
It was 2.0-rc with the try/except/finally fixed (018608160299) as mercurial/httpconnection.py does not exist in 89c80c3dc584. I just forgot another 'make local' after checking that the bug already was present in 89c80c3dc584 and was just not catched by the tests.
So apparently it fails with both 2.4.1 and 2.4.2 but works with 2.4.3. Has it worked with these Python versions before? Is it a regression? What changeset broke it in the first place?
It's probably this changeset in 2.4.3: http://hg.python.org/cpython/rev/ac02f655b31e Found with: $ hg log -vpr '::v2.4.3 -::v2.4.1 and keyword(urllib2)' on the cpython repo.
Mads, 89c80c3dc584 introduced the uri.split and exposes this problem. With its parent, 3e544c074459, it works fine. You can test with the repository http://hg.intevation.org/tmp/login/ (user and password are "test")
From one point of view: It broke 2½ years ago for the oldest and (probably) least used Python versions. That makes it a regression, but I would say "cbb". The risk of introducing a fix/workaround is probably higher than the benefit. From another point of view: Python acknowledged that it was a Python bug and they fixed it. We could perhaps work around it, but the right place to fix it would be Python. Python could be updated to 2.4.3 or the fix could be backported.
* Mads Kiilerich <bugs@mercurial.selenic.com> [20111017 16:26]: > >From one point of view: It broke 2½ years ago for the oldest and (probably) > least used Python versions. That makes it a regression, but I would say > "cbb". The risk of introducing a fix/workaround is probably higher than the > benefit. > > >From another point of view: Python acknowledged that it was a Python bug and > they fixed it. We could perhaps work around it, but the right place to fix > it would be Python. Python could be updated to 2.4.3 or the fix could be > backported. What about catching the exception and producing a better message than this long traceback? This should reduce the risk and the required work/testing.
How about something as simple as this: diff -r ebeac9c41456 mercurial/httpconnection.py --- a/mercurial/httpconnection.py Sun Oct 16 22:15:43 2011 -0500 +++ b/mercurial/httpconnection.py Mon Oct 17 10:07:34 2011 -0500 @@ -70,7 +70,11 @@ gdict[setting] = val # Find the best match - scheme, hostpath = uri.split('://', 1) + if '://' in uri: + scheme, hostpath = uri.split('://', 1) + else: + # py2.4.1 doesn't provide the full URI + scheme, hostpath = 'http', uri bestuser = None bestlen = 0 bestauth = None
Fixed by http://selenic.com/repo/hg/rev/b3083042bdda Matt Mackall <mpm@selenic.com> auth: fix realm handling with Python < 2.4.3 (issue2739) (please test the fix)
The path will not be available, so when using the example in the hgrc docs: foo.prefix = hg.intevation.org/mercurial a user of python2.4 can only use foo.prefix = hg.intevation.org But since the alternative is to not being able to access the repo at all the fix seems good enough. I'll test it.
test-http.t still fails with 1ae824142c01 on python 2.4.1, but in a less scary way: --- /tmp/thomas/tah/tests/test-http.t +++ /tmp/thomas/tah/tests/test-http.t.err @@ -136,7 +136,8 @@ abort: http authorization required [255] $ hg id http://user:pass@localhost:$HGPORT2/ - 5fed3813f7f5 + abort: http authorization required + [255] $ echo '[auth]' >> .hg/hgrc $ echo 'l.schemes=http' >> .hg/hgrc $ echo 'l.prefix=*' >> .hg/hgrc @@ -151,11 +152,9 @@ $ hg id http://user:pass@localhost:$HGPORT2/ 5fed3813f7f5 $ hg id http://user2@localhost:$HGPORT2/ - abort: http authorization required - [255] + 5fed3813f7f5 $ hg id http://user:pass2@localhost:$HGPORT2/ - abort: HTTP Error 403: no - [255] + 5fed3813f7f5 $ cd ..
The test fails, because with b3083042bdda the client always sends what is configured in hgrc, not what is in the requested URL.
--- Bug imported by bugzilla@serpentine.com 2012-05-12 09:18 EDT --- This bug was previously known as _bug_ 2739 at http://mercurial.selenic.com/bts/issue2739
Stale, closing.