diff options
-rw-r--r-- | Documentation/config.txt | 5 | ||||
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | environment.c | 4 | ||||
-rw-r--r-- | sha1_file.c | 5 |
6 files changed, 28 insertions, 1 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index 31885690f0..d31adb6719 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -429,6 +429,11 @@ relatively high IO latencies. With this set to 'true', git will do the index comparison to the filesystem data in parallel, allowing overlapping IO's. +core.unreliableHardlinks:: + Some filesystem drivers cannot properly handle hardlinking a file + and deleting the source right away. In such a case, you need to + set this config variable to 'true'. + alias.*:: Command aliases for the linkgit:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation @@ -171,6 +171,10 @@ all:: # 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. +# +# Define UNRELIABLE_HARDLINKS if your operating systems has problems when +# hardlinking a file to another name and unlinking the original file right +# away (some NTFS drivers seem to zero the contents in that scenario). GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN @@ -835,6 +839,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_NSEC = YesPlease USE_WIN32_MMAP = YesPlease UNRELIABLE_FSTAT = UnfortunatelyYes + UNRELIABLE_HARDLINKS = UnfortunatelySometimes COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" @@ -1018,6 +1023,9 @@ else COMPAT_OBJS += compat/win32mmap.o endif endif +ifdef UNRELIABLE_HARDLINKS + COMPAT_CFLAGS += -DUNRELIABLE_HARDLINKS=1 +endif ifdef NO_PREAD COMPAT_CFLAGS += -DNO_PREAD COMPAT_OBJS += compat/pread.o @@ -554,6 +554,8 @@ extern enum branch_track git_branch_track; extern enum rebase_setup_type autorebase; extern enum push_default_type push_default; +extern int unreliable_hardlinks; + #define GIT_REPO_VERSION 0 extern int repository_format_version; extern int check_repository_format(void); @@ -495,6 +495,11 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.unreliablehardlinks")) { + unreliable_hardlinks = git_config_bool(var, value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/environment.c b/environment.c index 4696885b22..10578d24d7 100644 --- a/environment.c +++ b/environment.c @@ -43,6 +43,10 @@ unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; enum branch_track git_branch_track = BRANCH_TRACK_REMOTE; enum rebase_setup_type autorebase = AUTOREBASE_NEVER; enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; +#ifndef UNRELIABLE_HARDLINKS +#define UNRELIABLE_HARDLINKS 0 +#endif +int unreliable_hardlinks = UNRELIABLE_HARDLINKS; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/sha1_file.c b/sha1_file.c index 8fe135dc61..11969fc161 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2225,7 +2225,9 @@ int move_temp_to_file(const char *tmpfile, const char *filename) { int ret = 0; - if (link(tmpfile, filename)) + if (unreliable_hardlinks) + goto try_rename; + else if (link(tmpfile, filename)) ret = errno; /* @@ -2240,6 +2242,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename) * left to unlink. */ if (ret && ret != EEXIST) { + try_rename: if (!rename(tmpfile, filename)) goto out; ret = errno; |