[PATCH 1 of 8] Add a new function, fspath
Paul Moore
p.f.moore at gmail.com
Wed Apr 30 17:37:23 UTC 2008
# HG changeset patch
# User "Paul Moore <p.f.moore at gmail.com>"
# Date 1209573914 -3600
# Node ID 4c332d2df388086257be74380d53701631fd3a2e
# Parent 7758fc67c39fd22b1025faa02a69b49acfdb557c
Add a new function, fspath
The function, given a filename and an (optional) root, returns the filename
modified to use the case actually stored in the filesystem (if the file does
not exist, return a default value).
A generic implementation is provided in util.py, with a faster win32-specific
implementation (using win32api.FindFiles) in util_win32.py.
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -868,6 +868,45 @@
return True
except:
return True
+
+def fspath(name, root='', default=None):
+ '''Get name in the case stored in the filesystem
+
+ The filename 'name' is relative to the path 'root' (if given).
+ If the file does not exist, return default (or name unchanged if default
+ is not given). Otherwise, return the version of name with case as stored
+ in the filesystem.
+ '''
+ if not os.path.exists(os.path.join(root, name)):
+ if default is None:
+ return name
+ return default
+ parts = []
+ while name:
+ dir, leaf = os.path.split(name)
+
+ # Scan os.listdir for a name that matches leaf except for case
+ leaf_l = leaf.lower()
+ for n in os.listdir(os.path.join(root, dir)):
+ if n.lower() == leaf_l:
+ parts.append(n)
+ break
+ else:
+ # This should never happen, as the file exists so it should
+ # show up in os.listdir (even hidden files on Windows do).
+ # But just in case, append the leafname unchanged if it happens.
+ parts.append(leaf)
+
+ # Get the actual separator used in 'name', as we want to match
+ # whichever of os.sep or os.altsep was used.
+ if dir:
+ sep = name[len(dir)]
+ parts.append(sep)
+
+ name = dir
+
+ parts.reverse()
+ return ''.join(parts)
def checkexec(path):
"""
diff --git a/mercurial/util_win32.py b/mercurial/util_win32.py
--- a/mercurial/util_win32.py
+++ b/mercurial/util_win32.py
@@ -369,3 +369,50 @@
def handler(event):
win32process.ExitProcess(1)
win32api.SetConsoleCtrlHandler(handler)
+
+def fspath(name, root='', default=None):
+ '''Get name in the case stored in the filesystem
+
+ The filename 'name' is relative to the path 'root' (if given).
+ If the file does not exist, return default (or name unchanged if default
+ is not given). Otherwise, return the version of name with case as stored
+ in the filesystem.
+ '''
+ if not os.path.exists(os.path.join(root, name)):
+ if default is None:
+ return name
+ return default
+ parts = []
+ while name:
+ dir, leaf = os.path.split(name)
+
+ fullpath = os.path.join(root, name)
+ osleaf = None
+ if os.path.isdir(fullpath):
+ # win32api.FindFiles does the wrong thing on directories :-(
+ # So fall back to a slower os.listdir scan.
+ filelist = os.listdir(os.path.dirname(fullpath))
+ leaf_l = leaf.lower()
+ for f in filelist:
+ if f.lower() == leaf_l:
+ osleaf = f
+ break
+ else:
+ filelist = win32api.FindFiles(fullpath)
+ if len(filelist) == 1:
+ osleaf = filelist[0][8]
+ if osleaf is not None:
+ parts.append(osleaf)
+ else:
+ parts.append(leaf)
+
+ # Get the actual separator used in 'name', as we want to match
+ # whichever of os.sep or os.altsep was used.
+ if dir:
+ sep = name[len(dir)]
+ parts.append(sep)
+
+ name = dir
+
+ parts.reverse()
+ return ''.join(parts)
More information about the Mercurial-devel
mailing list