Mercurial > hg
changeset 9238:40196d036a71
util: add realpath() for getting the 'true' path.
The function is implemented for Mac OS X using the F_GETPATH fcntl,
and a basic implementation for Windows is provided as well. On other
POSIX systems, vanilla os.path.realpath() is used.
author | Dan Villiom Podlaski Christiansen <danchr@gmail.com> |
---|---|
date | Sun, 26 Jul 2009 17:25:08 +0200 |
parents | abc198bca7c1 |
children | 26fa0e31011d |
files | mercurial/posix.py mercurial/windows.py |
diffstat | 2 files changed, 48 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/posix.py Fri Jul 24 00:40:00 2009 +0200 +++ b/mercurial/posix.py Sun Jul 26 17:25:08 2009 +0200 @@ -7,7 +7,7 @@ from i18n import _ import osutil -import os, sys, errno, stat, getpass, pwd, grp +import os, sys, errno, stat, getpass, pwd, grp, fcntl posixfile = open nulldev = '/dev/null' @@ -104,6 +104,44 @@ def localpath(path): return path +if sys.platform == 'darwin': + def realpath(path): + ''' + Returns the true, canonical file system path equivalent to the given + path. + + Equivalent means, in this case, resulting in the same, unique + file system link to the path. Every file system entry, whether a file, + directory, hard link or symbolic link or special, will have a single + path preferred by the system, but may allow multiple, differing path + lookups to point to it. + + Most regular UNIX file systems only allow a file system entry to be + looked up by its distinct path. Obviously, this does not apply to case + insensitive file systems, whether case preserving or not. The most + complex issue to deal with is file systems transparently reencoding the + path, such as the non-standard Unicode normalisation required for HFS+ + and HFSX. + ''' + # Constants copied from /usr/include/sys/fcntl.h + F_GETPATH = 50 + O_SYMLINK = 0x200000 + + try: + fd = os.open(path, O_SYMLINK) + except OSError, err: + if err.errno is errno.ENOENT: + return path + raise + + try: + return fcntl.fcntl(fd, F_GETPATH, '\0' * 1024).rstrip('\0') + finally: + os.close(fd) +else: + # Fallback to the likely inadequate Python builtin function. + realpath = os.path.realpath + def shellquote(s): if os.sys.platform == 'OpenVMS': return '"%s"' % s
--- a/mercurial/windows.py Fri Jul 24 00:40:00 2009 +0200 +++ b/mercurial/windows.py Sun Jul 26 17:25:08 2009 +0200 @@ -126,6 +126,15 @@ def normpath(path): return pconvert(os.path.normpath(path)) +def realpath(path): + ''' + Returns the true, canonical file system path equivalent to the given + path. + ''' + # TODO: There may be a more clever way to do this that also handles other, + # less common file systems. + return os.path.normpath(os.path.normcase(os.path.realpath(path))) + def samestat(s1, s2): return False