Skip to content

Commit d2b3f46

Browse files
sunzhuoshidscho
andcommitted
Add config option windows.appendAtomically
Atomic append on windows is only supported on local disk files, and it may cause errors in other situations, e.g. network file system. If that is the case, this config option should be used to turn atomic append off. Co-Authored-By: Johannes Schindelin <[email protected]> Signed-off-by: 孙卓识 <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 4012470 commit d2b3f46

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

Documentation/config.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,4 +537,6 @@ include::config/versionsort.txt[]
537537

538538
include::config/web.txt[]
539539

540+
include::config/windows.txt[]
541+
540542
include::config/worktree.txt[]

Documentation/config/windows.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
windows.appendAtomically::
2+
By default, append atomic API is used on windows. But it works only with
3+
local disk files, if you're working on a network file system, you should
4+
set it false to turn it off.

compat/mingw.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ static int is_local_named_pipe_path(const char *filename)
534534

535535
int mingw_open (const char *filename, int oflags, ...)
536536
{
537+
static int append_atomically = -1;
537538
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
538539
va_list args;
539540
unsigned mode;
@@ -550,7 +551,16 @@ int mingw_open (const char *filename, int oflags, ...)
550551
return -1;
551552
}
552553

553-
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
554+
/*
555+
* Only set append_atomically to default value(1) when repo is initialized
556+
* and fail to get config value
557+
*/
558+
if (append_atomically < 0 && the_repository && the_repository->commondir &&
559+
git_config_get_bool("windows.appendatomically", &append_atomically))
560+
append_atomically = 1;
561+
562+
if (append_atomically && (oflags & O_APPEND) &&
563+
!is_local_named_pipe_path(filename))
554564
open_fn = mingw_open_append;
555565
else
556566
open_fn = _wopen;
@@ -699,8 +709,26 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
699709
HANDLE h = (HANDLE) _get_osfhandle(fd);
700710
if (GetFileType(h) == FILE_TYPE_PIPE)
701711
errno = EPIPE;
702-
else
712+
else {
713+
wchar_t path[MAX_LONG_PATH];
714+
DWORD ret = GetFinalPathNameByHandleW(h, path,
715+
ARRAY_SIZE(path), 0);
716+
UINT drive_type = ret > 0 && ret < ARRAY_SIZE(path) ?
717+
GetDriveTypeW(path) : DRIVE_UNKNOWN;
718+
719+
/*
720+
* The default atomic append causes such an error on
721+
* network file systems, in such a case, it should be
722+
* turned off via config.
723+
*
724+
* `drive_type` of UNC path: DRIVE_NO_ROOT_DIR
725+
*/
726+
if (DRIVE_NO_ROOT_DIR == drive_type || DRIVE_REMOTE == drive_type)
727+
warning("invalid write operation detected; you may try:\n"
728+
"\n\tgit config windows.appendAtomically false");
729+
703730
errno = EINVAL;
731+
}
704732
}
705733

706734
return result;

0 commit comments

Comments
 (0)