@matheusbsbs / matheus-bagliano / commits / 34779c535c
Fork 0

Windows: Skip fstat/lstat optimization in write_entry()

Commit e4c72923 (write_entry(): use fstat() instead of lstat() when file is open, 2009-02-09) introduced an optimization of write_entry(). Unfortunately, we cannot take advantage of this optimization on Windows because there is no guarantee that the time stamps are updated before the file is closed: "The only guarantee about a file timestamp is that the file time is correctly reflected when the handle that makes the change is closed." (http://msdn.microsoft.com/en-us/library/ms724290(VS.85).aspx) The failure of this optimization on Windows can be observed most easily by running a 'git checkout' that has to update several large files. In this case, 'git checkout' will report modified files, but infact only the timestamps were incorrectly recorded in the index, as can be verified by a subsequent 'git diff', which shows no change. Dmitry Potapov reports the same fix needs on Cygwin; this commit contains his updates for that. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Sixt committed Apr 20, 2009 at 10:17 UTC 34779c535c4e121414197ab08b4b502a22a75433
3 files changed +17 -1
Makefile
+9
@@ -167,6 +167,10 @@ all::
167 # Define NO_EXTERNAL_GREP if you don't want "git grep" to ever call
168 # your external grep (e.g., if your system lacks grep, if its grep is
169 # broken, or spawning external process is slower than built-in grep git has).
170 +#
171 +# Define UNRELIABLE_FSTAT if your system's fstat does not return the same
172 +# information on a not yet closed file that lstat would return for the same
173 +# file after it was closed.
174
175 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
176 @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -803,6 +807,7 @@ ifeq ($(uname_S),HP-UX)
807 endif
808 ifneq (,$(findstring CYGWIN,$(uname_S)))
809 COMPAT_OBJS += compat/cygwin.o
810 + UNRELIABLE_FSTAT = UnfortunatelyYes
811 endif
812 ifneq (,$(findstring MINGW,$(uname_S)))
813 NO_PREAD = YesPlease
@@ -829,6 +834,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
834 NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
835 NO_NSEC = YesPlease
836 USE_WIN32_MMAP = YesPlease
837 + UNRELIABLE_FSTAT = UnfortunatelyYes
838 COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
839 COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
840 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@ -1107,6 +1113,9 @@ endif
1113 ifdef NO_EXTERNAL_GREP
1114 BASIC_CFLAGS += -DNO_EXTERNAL_GREP
1115 endif
1116 +ifdef UNRELIABLE_FSTAT
1117 + BASIC_CFLAGS += -DUNRELIABLE_FSTAT
1118 +endif
1119
1120 ifeq ($(TCLTK_PATH),)
1121 NO_TCLTK=NoThanks
entry.c
+2 -1
@@ -147,7 +147,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
147
148 wrote = write_in_full(fd, new, size);
149 /* use fstat() only when path == ce->name */
150 - if (state->refresh_cache && !to_tempfile && !state->base_dir_len) {
150 + if (fstat_is_reliable() &&
151 + state->refresh_cache && !to_tempfile && !state->base_dir_len) {
152 fstat(fd, &st);
153 fstat_done = 1;
154 }
git-compat-util.h
+6
@@ -408,4 +408,10 @@ void git_qsort(void *base, size_t nmemb, size_t size,
408 #endif
409 #endif
410
411 +#ifdef UNRELIABLE_FSTAT
412 +#define fstat_is_reliable() 0
413 +#else
414 +#define fstat_is_reliable() 1
415 +#endif
416 +
417 #endif