Skip to content

Commit 61cbb76

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 a672ede commit 61cbb76

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

Documentation/config.txt

+2
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,6 @@ include::config/versionsort.txt[]
539539

540540
include::config/web.txt[]
541541

542+
include::config/windows.txt[]
543+
542544
include::config/worktree.txt[]

Documentation/config/windows.txt

+4
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

+30-2
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ static int is_local_named_pipe_path(const char *filename)
535535

536536
int mingw_open (const char *filename, int oflags, ...)
537537
{
538+
static int append_atomically = -1;
538539
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
539540
va_list args;
540541
unsigned mode;
@@ -551,7 +552,16 @@ int mingw_open (const char *filename, int oflags, ...)
551552
return -1;
552553
}
553554

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

707735
return result;

0 commit comments

Comments
 (0)