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>
This commit is contained in:
parent
6ac6f87818
commit
34779c535c
9
Makefile
9
Makefile
@ -167,6 +167,10 @@ all::
|
||||
# Define NO_EXTERNAL_GREP if you don't want "git grep" to ever call
|
||||
# your external grep (e.g., if your system lacks grep, if its grep is
|
||||
# broken, or spawning external process is slower than built-in grep git has).
|
||||
#
|
||||
# Define UNRELIABLE_FSTAT if your system's fstat does not return the same
|
||||
# information on a not yet closed file that lstat would return for the same
|
||||
# file after it was closed.
|
||||
|
||||
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
||||
@$(SHELL_PATH) ./GIT-VERSION-GEN
|
||||
@ -803,6 +807,7 @@ ifeq ($(uname_S),HP-UX)
|
||||
endif
|
||||
ifneq (,$(findstring CYGWIN,$(uname_S)))
|
||||
COMPAT_OBJS += compat/cygwin.o
|
||||
UNRELIABLE_FSTAT = UnfortunatelyYes
|
||||
endif
|
||||
ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_PREAD = YesPlease
|
||||
@ -829,6 +834,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
UNRELIABLE_FSTAT = UnfortunatelyYes
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
|
||||
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
|
||||
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
||||
@ -1107,6 +1113,9 @@ endif
|
||||
ifdef NO_EXTERNAL_GREP
|
||||
BASIC_CFLAGS += -DNO_EXTERNAL_GREP
|
||||
endif
|
||||
ifdef UNRELIABLE_FSTAT
|
||||
BASIC_CFLAGS += -DUNRELIABLE_FSTAT
|
||||
endif
|
||||
|
||||
ifeq ($(TCLTK_PATH),)
|
||||
NO_TCLTK=NoThanks
|
||||
|
3
entry.c
3
entry.c
@ -147,7 +147,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
|
||||
|
||||
wrote = write_in_full(fd, new, size);
|
||||
/* use fstat() only when path == ce->name */
|
||||
if (state->refresh_cache && !to_tempfile && !state->base_dir_len) {
|
||||
if (fstat_is_reliable() &&
|
||||
state->refresh_cache && !to_tempfile && !state->base_dir_len) {
|
||||
fstat(fd, &st);
|
||||
fstat_done = 1;
|
||||
}
|
||||
|
@ -408,4 +408,10 @@ void git_qsort(void *base, size_t nmemb, size_t size,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UNRELIABLE_FSTAT
|
||||
#define fstat_is_reliable() 0
|
||||
#else
|
||||
#define fstat_is_reliable() 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user