comparison mercurial/util.py @ 6676:33045179d079

Add a new function, fspath The function, given a relative filename and a root, returns the filename modified to use the case actually stored in the filesystem (or None if the file does not exist). The returned name is relative to the root, but retains the path separators used in the input path. (This is not strictly necessary, but retaining the path separators minimises misleading test suite failures). A win32-specific implementation (using win32api.FindFiles) is possible, but it has not been implemented as testing seems to demonstrate that the win32-specific code is not significantly faster (thanks to the caching of results in the generic code).
author Paul Moore <p.f.moore@gmail.com>
date Fri, 06 Jun 2008 19:23:23 +0100
parents 99a92acafdb9
children 86e8187b721a
comparison
equal deleted inserted replaced
6675:03a836ca6fde 6676:33045179d079
857 return False 857 return False
858 return True 858 return True
859 except: 859 except:
860 return True 860 return True
861 861
862 _fspathcache = {}
863 def fspath(name, root):
864 '''Get name in the case stored in the filesystem
865
866 The name is either relative to root, or it is an absolute path starting
867 with root. Note that this function is unnecessary, and should not be
868 called, for case-sensitive filesystems (simply because it's expensive).
869 '''
870 # If name is absolute, make it relative
871 if name.lower().startswith(root.lower()):
872 l = len(root)
873 if name[l] == os.sep or name[l] == os.altsep:
874 l = l + 1
875 name = name[l:]
876
877 if not os.path.exists(os.path.join(root, name)):
878 return None
879
880 seps = os.sep
881 if os.altsep:
882 seps = seps + os.altsep
883 # Protect backslashes. This gets silly very quickly.
884 seps.replace('\\','\\\\')
885 pattern = re.compile(r'([^%s]+)|([%s]+)' % (seps, seps))
886 dir = os.path.normcase(os.path.normpath(root))
887 result = []
888 for part, sep in pattern.findall(name):
889 if sep:
890 result.append(sep)
891 continue
892
893 if dir not in _fspathcache:
894 _fspathcache[dir] = os.listdir(dir)
895 contents = _fspathcache[dir]
896
897 lpart = part.lower()
898 for n in contents:
899 if n.lower() == lpart:
900 result.append(n)
901 break
902 else:
903 # Cannot happen, as the file exists!
904 result.append(part)
905 dir = os.path.join(dir, lpart)
906
907 return ''.join(result)
908
862 def checkexec(path): 909 def checkexec(path):
863 """ 910 """
864 Check whether the given path is on a filesystem with UNIX-like exec flags 911 Check whether the given path is on a filesystem with UNIX-like exec flags
865 912
866 Requires a directory (like /foo/.hg) 913 Requires a directory (like /foo/.hg)