Skip to content

Commit 54bea87

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 97dde63 commit 54bea87

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

Documentation/config.txt

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

548548
include::config/web.txt[]
549549

550+
include::config/windows.txt[]
551+
550552
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: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "gettext.h"
1919
#define SECURITY_WIN32
2020
#include <sspi.h>
21+
#include "../repository.h"
2122

2223
#define HCAST(type, handle) ((type)(intptr_t)handle)
2324

@@ -547,6 +548,7 @@ static int is_local_named_pipe_path(const char *filename)
547548

548549
int mingw_open (const char *filename, int oflags, ...)
549550
{
551+
static int append_atomically = -1;
550552
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
551553
va_list args;
552554
unsigned mode;
@@ -563,7 +565,16 @@ int mingw_open (const char *filename, int oflags, ...)
563565
return -1;
564566
}
565567

566-
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
568+
/*
569+
* Only set append_atomically to default value(1) when repo is initialized
570+
* and fail to get config value
571+
*/
572+
if (append_atomically < 0 && the_repository && the_repository->commondir &&
573+
git_config_get_bool("windows.appendatomically", &append_atomically))
574+
append_atomically = 1;
575+
576+
if (append_atomically && (oflags & O_APPEND) &&
577+
!is_local_named_pipe_path(filename))
567578
open_fn = mingw_open_append;
568579
else
569580
open_fn = _wopen;
@@ -712,9 +723,28 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
712723

713724
/* check if fd is a pipe */
714725
HANDLE h = (HANDLE) _get_osfhandle(fd);
715-
if (GetFileType(h) != FILE_TYPE_PIPE)
726+
if (GetFileType(h) != FILE_TYPE_PIPE) {
727+
if (orig == EINVAL) {
728+
wchar_t path[MAX_PATH];
729+
DWORD ret = GetFinalPathNameByHandleW(h, path,
730+
ARRAY_SIZE(path), 0);
731+
UINT drive_type = ret > 0 && ret < ARRAY_SIZE(path) ?
732+
GetDriveTypeW(path) : DRIVE_UNKNOWN;
733+
734+
/*
735+
* The default atomic append causes such an error on
736+
* network file systems, in such a case, it should be
737+
* turned off via config.
738+
*
739+
* `drive_type` of UNC path: DRIVE_NO_ROOT_DIR
740+
*/
741+
if (DRIVE_NO_ROOT_DIR == drive_type || DRIVE_REMOTE == drive_type)
742+
warning("invalid write operation detected; you may try:\n"
743+
"\n\tgit config windows.appendAtomically false");
744+
}
745+
716746
errno = orig;
717-
else if (orig == EINVAL)
747+
} else if (orig == EINVAL)
718748
errno = EPIPE;
719749
else {
720750
DWORD buf_size;

0 commit comments

Comments
 (0)