cygwin: Remove the Win32 l/stat() implementation
authorRamsay Jones <ramsay@ramsay1.demon.co.uk>
Sat, 22 Jun 2013 19:42:47 +0000 (20:42 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Jul 2013 17:44:17 +0000 (10:44 -0700)
Commit adbc0b6b ("cygwin: Use native Win32 API for stat", 30-09-2008)
added a Win32 specific implementation of the stat functions. In order
to handle absolute paths, cygwin mount points and symbolic links, this
implementation may fall back on the standard cygwin l/stat() functions.
Also, the choice of cygwin or Win32 functions is made lazily (by the
first call(s) to l/stat) based on the state of some config variables.

Unfortunately, this "schizophrenic stat" implementation has been the
source of many problems ever since. For example, see commits 7faee6b8,
79748439, 452993c2, 085479e7, b8a97333, 924aaf3e, 05bab3ea and 0117c2f0.

In order to avoid further problems, such as the issue raised by the new
reference handling API, remove the Win32 l/stat() implementation.

Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config.txt
Makefile
compat/cygwin.c [deleted file]
compat/cygwin.h [deleted file]
config.mak.uname
contrib/completion/git-completion.bash
git-compat-util.h
help.c
path.c
index 81856dd5a2559149b9dcdf263ed5c3212a07d480..fe49cb9d47e596c7e1b39cd355c52906244d9d4e 100644 (file)
@@ -213,17 +213,6 @@ The default is true, except linkgit:git-clone[1] or linkgit:git-init[1]
 will probe and set core.fileMode false if appropriate when the
 repository is created.
 
-core.ignoreCygwinFSTricks::
-       This option is only used by Cygwin implementation of Git. If false,
-       the Cygwin stat() and lstat() functions are used. This may be useful
-       if your repository consists of a few separate directories joined in
-       one hierarchy using Cygwin mount. If true, Git uses native Win32 API
-       whenever it is possible and falls back to Cygwin functions only to
-       handle symbol links. The native mode is more than twice faster than
-       normal Cygwin l/stat() functions. True by default, unless core.filemode
-       is true, in which case ignoreCygwinFSTricks is ignored as Cygwin's
-       POSIX emulation is required to support core.filemode.
-
 core.ignorecase::
        If true, this option enables various workarounds to enable
        Git to work better on filesystems that are not case sensitive,
index 0600eb46db487c88e24dc3b4089db062ad6350ac..9c0da06e4abb30c5524377fe7affa63a4cd97850 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -654,7 +654,6 @@ LIB_H += color.h
 LIB_H += column.h
 LIB_H += commit.h
 LIB_H += compat/bswap.h
-LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
 LIB_H += compat/obstack.h
 LIB_H += compat/poll/poll.h
diff --git a/compat/cygwin.c b/compat/cygwin.c
deleted file mode 100644 (file)
index 91ce5d4..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-#define CYGWIN_C
-#define WIN32_LEAN_AND_MEAN
-#include <sys/stat.h>
-#include <sys/errno.h>
-#include "win32.h"
-#include "../git-compat-util.h"
-#include "../cache.h" /* to read configuration */
-
-/*
- * Return POSIX permission bits, regardless of core.ignorecygwinfstricks
- */
-int cygwin_get_st_mode_bits(const char *path, int *mode)
-{
-       struct stat st;
-       if (lstat(path, &st) < 0)
-               return -1;
-       *mode = st.st_mode;
-       return 0;
-}
-
-static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
-{
-       long long winTime = ((long long)ft->dwHighDateTime << 32) +
-                       ft->dwLowDateTime;
-       winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
-       /* convert 100-nsecond interval to seconds and nanoseconds */
-       ts->tv_sec = (time_t)(winTime/10000000);
-       ts->tv_nsec = (long)(winTime - ts->tv_sec*10000000LL) * 100;
-}
-
-#define size_to_blocks(s) (((s)+511)/512)
-
-/* do_stat is a common implementation for cygwin_lstat and cygwin_stat.
- *
- * To simplify its logic, in the case of cygwin symlinks, this implementation
- * falls back to the cygwin version of stat/lstat, which is provided as the
- * last argument.
- */
-static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat)
-{
-       WIN32_FILE_ATTRIBUTE_DATA fdata;
-
-       if (file_name[0] == '/')
-               return cygstat (file_name, buf);
-
-       if (!(errno = get_file_attr(file_name, &fdata))) {
-               /*
-                * If the system attribute is set and it is not a directory then
-                * it could be a symbol link created in the nowinsymlinks mode.
-                * Normally, Cygwin works in the winsymlinks mode, so this situation
-                * is very unlikely. For the sake of simplicity of our code, let's
-                * Cygwin to handle it.
-                */
-               if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
-                   !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
-                       return cygstat(file_name, buf);
-
-               /* fill out the stat structure */
-               buf->st_dev = buf->st_rdev = 0; /* not used by Git */
-               buf->st_ino = 0;
-               buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
-               buf->st_nlink = 1;
-               buf->st_uid = buf->st_gid = 0;
-#ifdef __CYGWIN_USE_BIG_TYPES__
-               buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) +
-                       fdata.nFileSizeLow;
-#else
-               buf->st_size = (off_t)fdata.nFileSizeLow;
-#endif
-               buf->st_blocks = size_to_blocks(buf->st_size);
-               filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim);
-               filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim);
-               filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim);
-               return 0;
-       } else if (errno == ENOENT) {
-               /*
-                * In the winsymlinks mode (which is the default), Cygwin
-                * emulates symbol links using Windows shortcut files. These
-                * files are formed by adding .lnk extension. So, if we have
-                * not found the specified file name, it could be that it is
-                * a symbol link. Let's Cygwin to deal with that.
-                */
-               return cygstat(file_name, buf);
-       }
-       return -1;
-}
-
-/* We provide our own lstat/stat functions, since the provided Cygwin versions
- * of these functions are too slow. These stat functions are tailored for Git's
- * usage, and therefore they are not meant to be complete and correct emulation
- * of lstat/stat functionality.
- */
-static int cygwin_lstat(const char *path, struct stat *buf)
-{
-       return do_stat(path, buf, lstat);
-}
-
-static int cygwin_stat(const char *path, struct stat *buf)
-{
-       return do_stat(path, buf, stat);
-}
-
-
-/*
- * At start up, we are trying to determine whether Win32 API or cygwin stat
- * functions should be used. The choice is determined by core.ignorecygwinfstricks.
- * Reading this option is not always possible immediately as git_dir may
- * not be set yet. So until it is set, use cygwin lstat/stat functions.
- * However, if core.filemode is set, we must use the Cygwin posix
- * stat/lstat as the Windows stat functions do not determine posix filemode.
- *
- * Note that git_cygwin_config() does NOT call git_default_config() and this
- * is deliberate.  Many commands read from config to establish initial
- * values in variables and later tweak them from elsewhere (e.g. command line).
- * init_stat() is called lazily on demand, typically much late in the program,
- * and calling git_default_config() from here would break such variables.
- */
-static int native_stat = 1;
-static int core_filemode = 1; /* matches trust_executable_bit default */
-
-static int git_cygwin_config(const char *var, const char *value, void *cb)
-{
-       if (!strcmp(var, "core.ignorecygwinfstricks"))
-               native_stat = git_config_bool(var, value);
-       else if (!strcmp(var, "core.filemode"))
-               core_filemode = git_config_bool(var, value);
-       return 0;
-}
-
-static int init_stat(void)
-{
-       if (have_git_dir() && git_config(git_cygwin_config,NULL)) {
-               if (!core_filemode && native_stat) {
-                       cygwin_stat_fn = cygwin_stat;
-                       cygwin_lstat_fn = cygwin_lstat;
-               } else {
-                       cygwin_stat_fn = stat;
-                       cygwin_lstat_fn = lstat;
-               }
-               return 0;
-       }
-       return 1;
-}
-
-static int cygwin_stat_stub(const char *file_name, struct stat *buf)
-{
-       return (init_stat() ? stat : *cygwin_stat_fn)(file_name, buf);
-}
-
-static int cygwin_lstat_stub(const char *file_name, struct stat *buf)
-{
-       return (init_stat() ? lstat : *cygwin_lstat_fn)(file_name, buf);
-}
-
-stat_fn_t cygwin_stat_fn = cygwin_stat_stub;
-stat_fn_t cygwin_lstat_fn = cygwin_lstat_stub;
-
diff --git a/compat/cygwin.h b/compat/cygwin.h
deleted file mode 100644 (file)
index c04965a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-typedef int (*stat_fn_t)(const char*, struct stat*);
-extern stat_fn_t cygwin_stat_fn;
-extern stat_fn_t cygwin_lstat_fn;
-int cygwin_get_st_mode_bits(const char *path, int *mode);
-
-#define get_st_mode_bits(p,m) cygwin_get_st_mode_bits((p),(m))
-#ifndef CYGWIN_C
-/* cygwin.c needs the original lstat() */
-#define stat(path, buf) (*cygwin_stat_fn)(path, buf)
-#define lstat(path, buf) (*cygwin_lstat_fn)(path, buf)
-#endif
index 7ac541e9ebbe77b339846d8efafdd0b6f33fee95..1666551f61dd8a54e97b437f86f3c89854241ef6 100644 (file)
@@ -170,7 +170,6 @@ ifeq ($(uname_O),Cygwin)
        # Try commenting this out if you suspect MMAP is more efficient
        NO_MMAP = YesPlease
        X = .exe
-       COMPAT_OBJS += compat/cygwin.o
        UNRELIABLE_FSTAT = UnfortunatelyYes
        SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
 endif
index fa3ae1e8535c786dc724ab7a73cccb6f3bfca8de..eacba2ff69abb636e883c7c8d0bbaf3efd34b424 100644 (file)
@@ -1957,7 +1957,6 @@ _git_config ()
                core.fileMode
                core.fsyncobjectfiles
                core.gitProxy
-               core.ignoreCygwinFSTricks
                core.ignoreStat
                core.ignorecase
                core.logAllRefUpdates
index ff193f4aa236727cc9b87ddbaeac1975b8c40fa7..9f1eacaaae8d85f6391457143b74797a4d62a1f4 100644 (file)
 #include <poll.h>
 #endif
 
-extern int get_st_mode_bits(const char *path, int *mode);
-
 #if defined(__MINGW32__)
 /* pull in Windows compatibility stuff */
 #include "compat/mingw.h"
@@ -171,7 +169,6 @@ typedef unsigned long uintptr_t;
 #undef _XOPEN_SOURCE
 #include <grp.h>
 #define _XOPEN_SOURCE 600
-#include "compat/cygwin.h"
 #else
 #undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
 #include <grp.h>
diff --git a/help.c b/help.c
index 08c54ef1c1669edce960c52948b80340c36eb119..f068925bb7f26055fb699cda7173a0c06ac46a22 100644 (file)
--- a/help.c
+++ b/help.c
@@ -107,10 +107,7 @@ static int is_executable(const char *name)
            !S_ISREG(st.st_mode))
                return 0;
 
-#if defined(GIT_WINDOWS_NATIVE) || defined(__CYGWIN__)
-#if defined(__CYGWIN__)
-if ((st.st_mode & S_IXUSR) == 0)
-#endif
+#if defined(GIT_WINDOWS_NATIVE)
 {      /* cannot trust the executable bit, peek into the file instead */
        char buf[3] = { 0 };
        int n;
diff --git a/path.c b/path.c
index 04ff1487ed31685b6b3f7923f9bfbfc7217f70a0..4e7fae411f48d4f2d95b83f0517954d76450c0d7 100644 (file)
--- a/path.c
+++ b/path.c
@@ -5,13 +5,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 
-#ifndef get_st_mode_bits
-/*
- * The replacement lstat(2) we use on Cygwin is incomplete and
- * may return wrong permission bits. Most of the time we do not care,
- * but the callsites of this wrapper do care.
- */
-int get_st_mode_bits(const char *path, int *mode)
+static int get_st_mode_bits(const char *path, int *mode)
 {
        struct stat st;
        if (lstat(path, &st) < 0)
@@ -19,7 +13,6 @@ int get_st_mode_bits(const char *path, int *mode)
        *mode = st.st_mode;
        return 0;
 }
-#endif
 
 static char bad_path[] = "/bad-path/";