[PATCH 1 of 3] Add a new function, filesystem_case
Patrick Mézard
pmezard at gmail.com
Wed Apr 23 16:26:25 CDT 2008
Paul Moore a écrit :
> # HG changeset patch
> # User "Paul Moore <p.f.moore at gmail.com>"
> # Date 1208894004 -3600
> # Node ID 47aabfeb37f4a12d015b809afef81cb817e18972
> # Parent 90becd2b697eb345328dabb08e23262335bf9ff2
> Add a new function, filesystem_case
>
> 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 the name unchanged).
>
> An immplementation for Windows (case insensitive) and a no-op implementation
> for Unix is given. Unix can potentially have a case insensitive filesystem,
> but this implementation doesn't consider that. We also don't consider fancy
> stuff like Mac OS X normalisation forms. Suitable implementations for these
> can be added later.
>
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -1063,6 +1063,42 @@
> def localpath(path):
> return path.replace('/', '\\')
>
> + def filesystem_case(name, root=''):
We usually try to avoid long identifiers and underscores. What about "fspath()" ? It would also fit for a normalizing version on OSX.
> + '''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 it unchanged. Otherwise, return the
> + version of name with case as stored in the filesystem.
> + '''
> + if not os.path.exists(os.path.join(root, name)):
> + return name
Maybe we can have a fallback value instead (defaulting to None). That would shave one os.path.exists() call in the third patch.
> + 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. TODO: check if this is needed for
> + # hidden files, but they are probably weird anyway...
> + 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)
> +
I have no numbers to backup my claims but that really looks expensive to deal with a single file. At least, we should have a much faster version in util_win32, as suggested by Alexander Belchenko.
But the approach is good IMHO, let other comment on this.
--
Patrick Mézard
More information about the Mercurial-devel
mailing list