849 Check whether the given path is on a filesystem with UNIX-like exec flags |
849 Check whether the given path is on a filesystem with UNIX-like exec flags |
850 |
850 |
851 Requires a directory (like /foo/.hg) |
851 Requires a directory (like /foo/.hg) |
852 """ |
852 """ |
853 try: |
853 try: |
|
854 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH |
854 fh, fn = tempfile.mkstemp("", "", path) |
855 fh, fn = tempfile.mkstemp("", "", path) |
855 os.close(fh) |
856 os.close(fh) |
856 m = os.stat(fn).st_mode |
857 m = os.stat(fn).st_mode |
857 os.chmod(fn, m ^ 0111) |
858 # VFAT on Linux can flip mode but it doesn't persist a FS remount. |
858 r = (os.stat(fn).st_mode != m) |
859 # frequently we can detect it if files are created with exec bit on. |
|
860 new_file_has_exec = m & EXECFLAGS |
|
861 os.chmod(fn, m ^ EXECFLAGS) |
|
862 exec_flags_cannot_flip = (os.stat(fn).st_mode == m) |
859 os.unlink(fn) |
863 os.unlink(fn) |
860 except (IOError,OSError): |
864 except (IOError,OSError): |
861 # we don't care, the user probably won't be able to commit anyway |
865 # we don't care, the user probably won't be able to commit anyway |
862 return False |
866 return False |
863 return r |
867 return not (new_file_has_exec or exec_flags_cannot_flip) |
864 |
868 |
865 def execfunc(path, fallback): |
869 def execfunc(path, fallback): |
866 '''return an is_exec() function with default to fallback''' |
870 '''return an is_exec() function with default to fallback''' |
867 if checkexec(path): |
871 if checkexec(path): |
868 return lambda x: is_exec(os.path.join(path, x)) |
872 return lambda x: is_exec(os.path.join(path, x)) |