Mercurial > public > mercurial-scm > hg
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) |