Skip to content

Commit 6a54987

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 9028643 commit 6a54987

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

Documentation/config.txt

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

555555
include::config/web.txt[]
556556

557+
include::config/windows.txt[]
558+
557559
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

+33-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "gettext.h"
2121
#define SECURITY_WIN32
2222
#include <sspi.h>
23+
#include "../repository.h"
2324

2425
#define HCAST(type, handle) ((type)(intptr_t)handle)
2526

@@ -613,6 +614,7 @@ static int is_local_named_pipe_path(const char *filename)
613614

614615
int mingw_open (const char *filename, int oflags, ...)
615616
{
617+
static int append_atomically = -1;
616618
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
617619
va_list args;
618620
unsigned mode;
@@ -629,7 +631,16 @@ int mingw_open (const char *filename, int oflags, ...)
629631
return -1;
630632
}
631633

632-
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
634+
/*
635+
* Only set append_atomically to default value(1) when repo is initialized
636+
* and fail to get config value
637+
*/
638+
if (append_atomically < 0 && the_repository && the_repository->commondir &&
639+
git_config_get_bool("windows.appendatomically", &append_atomically))
640+
append_atomically = 1;
641+
642+
if (append_atomically && (oflags & O_APPEND) &&
643+
!is_local_named_pipe_path(filename))
633644
open_fn = mingw_open_append;
634645
else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
635646
open_fn = mingw_open_existing;
@@ -780,9 +791,28 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
780791

781792
/* check if fd is a pipe */
782793
HANDLE h = (HANDLE) _get_osfhandle(fd);
783-
if (GetFileType(h) != FILE_TYPE_PIPE)
794+
if (GetFileType(h) != FILE_TYPE_PIPE) {
795+
if (orig == EINVAL) {
796+
wchar_t path[MAX_PATH];
797+
DWORD ret = GetFinalPathNameByHandleW(h, path,
798+
ARRAY_SIZE(path), 0);
799+
UINT drive_type = ret > 0 && ret < ARRAY_SIZE(path) ?
800+
GetDriveTypeW(path) : DRIVE_UNKNOWN;
801+
802+
/*
803+
* The default atomic append causes such an error on
804+
* network file systems, in such a case, it should be
805+
* turned off via config.
806+
*
807+
* `drive_type` of UNC path: DRIVE_NO_ROOT_DIR
808+
*/
809+
if (DRIVE_NO_ROOT_DIR == drive_type || DRIVE_REMOTE == drive_type)
810+
warning("invalid write operation detected; you may try:\n"
811+
"\n\tgit config windows.appendAtomically false");
812+
}
813+
784814
errno = orig;
785-
else if (orig == EINVAL)
815+
} else if (orig == EINVAL)
786816
errno = EPIPE;
787817
else {
788818
DWORD buf_size;

0 commit comments

Comments
 (0)