Skip to content

Commit

Permalink
Add config option windows.appendAtomically
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
sunzhuoshi and dscho committed Sep 16, 2022
1 parent 5020b08 commit 0ba0416
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Documentation/config.txt
Expand Up @@ -539,4 +539,6 @@ include::config/versionsort.txt[]

include::config/web.txt[]

include::config/windows.txt[]

include::config/worktree.txt[]
4 changes: 4 additions & 0 deletions Documentation/config/windows.txt
@@ -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.
32 changes: 30 additions & 2 deletions compat/mingw.c
Expand Up @@ -535,6 +535,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;
Expand All @@ -551,7 +552,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 &&
git_config_get_bool("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
open_fn = _wopen;
Expand Down Expand Up @@ -700,8 +710,26 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
HANDLE h = (HANDLE) _get_osfhandle(fd);
if (GetFileType(h) == FILE_TYPE_PIPE)
errno = EPIPE;
else
else {
wchar_t path[MAX_LONG_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 = EINVAL;
}
}

return result;
Expand Down

0 comments on commit 0ba0416

Please sign in to comment.