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 <johannes.schindelin@gmx.de>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
孙卓识 2022-01-16 03:38:33 +08:00 committed by Johannes Schindelin
parent c5369ed69d
commit 3d4b5cb69b
3 changed files with 39 additions and 3 deletions

View File

@ -559,4 +559,6 @@ include::config/versionsort.adoc[]
include::config/web.adoc[]
include::config/windows.adoc[]
include::config/worktree.adoc[]

View File

@ -0,0 +1,4 @@
windows.appendAtomically::
By default, append atomic API is used on windows. But it works only with
local disk files, if you're working on a network file system, you should
set it false to turn it off.

View File

@ -8,6 +8,7 @@
#include "dir.h"
#include "environment.h"
#include "gettext.h"
#include "repository.h"
#include "run-command.h"
#include "strbuf.h"
#include "symlinks.h"
@ -623,6 +624,7 @@ static int is_local_named_pipe_path(const char *filename)
int mingw_open (const char *filename, int oflags, ...)
{
static int append_atomically = -1;
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
va_list args;
unsigned mode;
@ -642,7 +644,16 @@ int mingw_open (const char *filename, int oflags, ...)
return -1;
}
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
/*
* Only set append_atomically to default value(1) when repo is initialized
* and fail to get config value
*/
if (append_atomically < 0 && the_repository && the_repository->commondir &&
repo_config_get_bool(the_repository, "windows.appendatomically", &append_atomically))
append_atomically = 1;
if (append_atomically && (oflags & O_APPEND) &&
!is_local_named_pipe_path(filename))
open_fn = mingw_open_append;
else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
open_fn = mingw_open_existing;
@ -821,9 +832,28 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
/* check if fd is a pipe */
HANDLE h = (HANDLE) _get_osfhandle(fd);
if (GetFileType(h) != FILE_TYPE_PIPE)
if (GetFileType(h) != FILE_TYPE_PIPE) {
if (orig == EINVAL) {
wchar_t path[MAX_PATH];
DWORD ret = GetFinalPathNameByHandleW(h, path,
ARRAY_SIZE(path), 0);
UINT drive_type = ret > 0 && ret < ARRAY_SIZE(path) ?
GetDriveTypeW(path) : DRIVE_UNKNOWN;
/*
* The default atomic append causes such an error on
* network file systems, in such a case, it should be
* turned off via config.
*
* `drive_type` of UNC path: DRIVE_NO_ROOT_DIR
*/
if (DRIVE_NO_ROOT_DIR == drive_type || DRIVE_REMOTE == drive_type)
warning("invalid write operation detected; you may try:\n"
"\n\tgit config windows.appendAtomically false");
}
errno = orig;
else if (orig == EINVAL)
} else if (orig == EINVAL)
errno = EPIPE;
else {
DWORD buf_size;