# HG changeset patch # User Patrick Mezard # Date 2011-12-04 17:22:25 # Node ID 8f4bad72d8b15d3feb803e58f750e75853835a06 # Parent 63ff8fe3a8f05dda76e9df66573927b7a6dc2273 util: fix url.__str__() for windows file URLs Before: >>> str(url('file:///c:/tmp/foo/bar')) 'file:c%3C/tmp/foo/bar' After: >>> str(url('file:///c:/tmp/foo/bar')) 'file:///c%3C/tmp/foo/bar' The previous behaviour had no effect on mercurial itself (clone command for instance) because we fortunately called .localpath() on the parsed URL. hgsubversion was not so lucky and cloning a local subversion repository on Windows no longer worked on the default branch (it works on stable because de7e2fba4326 defeats the hasdriveletter() test in url class). I do not know if the %3C is correct or not but svn accepts file:// URLs containing it. Mads fixed it in de7e2fba4326, so we can always backport should the need arise. diff --git a/hgext/schemes.py b/hgext/schemes.py --- a/hgext/schemes.py +++ b/hgext/schemes.py @@ -72,9 +72,10 @@ class ShortRepository(object): return hg._peerlookup(url).instance(ui, url, create) def hasdriveletter(orig, path): - for scheme in schemes: - if path.startswith(scheme + ':'): - return False + if path: + for scheme in schemes: + if path.startswith(scheme + ':'): + return False return orig(path) schemes = { diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1629,6 +1629,8 @@ class url(object): 'path' >>> str(url('file:///tmp/foo/bar')) 'file:///tmp/foo/bar' + >>> str(url('file:///c:/tmp/foo/bar')) + 'file:///c%3A/tmp/foo/bar' >>> print url(r'bundle:foo\bar') bundle:foo\bar """ @@ -1643,8 +1645,11 @@ class url(object): s = self.scheme + ':' if self.user or self.passwd or self.host: s += '//' - elif self.scheme and (not self.path or self.path.startswith('/')): + elif self.scheme and (not self.path or self.path.startswith('/') + or hasdriveletter(self.path)): s += '//' + if hasdriveletter(self.path): + s += '/' if self.user: s += urllib.quote(self.user, safe=self._safechars) if self.passwd: @@ -1716,7 +1721,7 @@ def hasscheme(path): return bool(url(path).scheme) def hasdriveletter(path): - return path[1:2] == ':' and path[0:1].isalpha() + return path and path[1:2] == ':' and path[0:1].isalpha() def urllocalpath(path): return url(path, parsequery=False, parsefragment=False).localpath() diff --git a/tests/test-url.py b/tests/test-url.py --- a/tests/test-url.py +++ b/tests/test-url.py @@ -219,7 +219,7 @@ def test_url(): >>> u >>> str(u) - 'file:f%3Aoo/bar/baz' + 'file:///f%3Aoo/bar/baz' >>> u.localpath() 'f:oo/bar/baz'