mercurial/util.py
branchstable
changeset 15937 7ed056f1e97d
parent 15720 3bcfea777efc
child 16360 e5788269741a
--- a/mercurial/util.py	Tue Jan 17 11:29:32 2012 +0100
+++ b/mercurial/util.py	Thu Jan 19 14:34:32 2012 -0600
@@ -77,6 +77,11 @@
 
 # Python compatibility
 
+_notset = object()
+
+def safehasattr(thing, attr):
+    return getattr(thing, attr, _notset) is not _notset
+
 def sha1(s=''):
     '''
     Low-overhead wrapper around Python's SHA support
@@ -90,10 +95,6 @@
 
     return _fastsha1(s)
 
-_notset = object()
-def safehasattr(thing, attr):
-    return getattr(thing, attr, _notset) is not _notset
-
 def _fastsha1(s=''):
     # This function will import sha1 from hashlib or sha (whichever is
     # available) and overwrite itself with it on the first call.
@@ -106,18 +107,15 @@
     _fastsha1 = sha1 = _sha1
     return _sha1(s)
 
-import __builtin__
-
-if sys.version_info[0] < 3:
-    def fakebuffer(sliceable, offset=0):
-        return sliceable[offset:]
-else:
-    def fakebuffer(sliceable, offset=0):
-        return memoryview(sliceable)[offset:]
 try:
-    buffer
+    buffer = buffer
 except NameError:
-    __builtin__.buffer = fakebuffer
+    if sys.version_info[0] < 3:
+        def buffer(sliceable, offset=0):
+            return sliceable[offset:]
+    else:
+        def buffer(sliceable, offset=0):
+            return memoryview(sliceable)[offset:]
 
 import subprocess
 closefds = os.name == 'posix'
@@ -616,20 +614,17 @@
 def fspath(name, root):
     '''Get name in the case stored in the filesystem
 
-    The name is either relative to root, or it is an absolute path starting
-    with root. Note that this function is unnecessary, and should not be
+    The name should be relative to root, and be normcase-ed for efficiency.
+
+    Note that this function is unnecessary, and should not be
     called, for case-sensitive filesystems (simply because it's expensive).
 
-    Both name and root should be normcase-ed.
+    The root should be normcase-ed, too.
     '''
-    # If name is absolute, make it relative
-    if name.startswith(root):
-        l = len(root)
-        if name[l] == os.sep or name[l] == os.altsep:
-            l = l + 1
-        name = name[l:]
-
-    if not os.path.lexists(os.path.join(root, name)):
+    def find(p, contents):
+        for n in contents:
+            if normcase(n) == p:
+                return n
         return None
 
     seps = os.sep
@@ -649,14 +644,15 @@
             _fspathcache[dir] = os.listdir(dir)
         contents = _fspathcache[dir]
 
-        lenp = len(part)
-        for n in contents:
-            if lenp == len(n) and normcase(n) == part:
-                result.append(n)
-                break
-        else:
-            # Cannot happen, as the file exists!
-            result.append(part)
+        found = find(part, contents)
+        if not found:
+            # retry "once per directory" per "dirstate.walk" which
+            # may take place for each patches of "hg qpush", for example
+            contents = os.listdir(dir)
+            _fspathcache[dir] = contents
+            found = find(part, contents)
+
+        result.append(found or part)
         dir = os.path.join(dir, part)
 
     return ''.join(result)
@@ -1502,7 +1498,7 @@
     """
 
     _safechars = "!~*'()+"
-    _safepchars = "/!~*'()+"
+    _safepchars = "/!~*'()+:"
     _matchscheme = re.compile(r'^[a-zA-Z0-9+.\-]+:').match
 
     def __init__(self, path, parsequery=True, parsefragment=True):
@@ -1614,8 +1610,8 @@
 
         Examples:
 
-        >>> str(url('http://user:pw@host:80/?foo#bar'))
-        'http://user:pw@host:80/?foo#bar'
+        >>> str(url('http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
+        'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
         >>> str(url('http://user:pw@host:80/?foo=bar&baz=42'))
         'http://user:pw@host:80/?foo=bar&baz=42'
         >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz'))
@@ -1637,7 +1633,7 @@
         >>> str(url('file:///tmp/foo/bar'))
         'file:///tmp/foo/bar'
         >>> str(url('file:///c:/tmp/foo/bar'))
-        'file:///c%3A/tmp/foo/bar'
+        'file:///c:/tmp/foo/bar'
         >>> print url(r'bundle:foo\bar')
         bundle:foo\bar
         """