From df38aa7058ecbb635c0fe92662234a10ffa99fc9 Mon Sep 17 00:00:00 2001 From: Andrey Zabavnikov Date: Thu, 3 Nov 2022 20:22:19 +0300 Subject: [PATCH] amend! Add config option `windows.appendAtomically` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. With these edits, status for old-style submodules with commondir needs to be fixed, due to the following. In some setups, old-style submodules (i.e. the ones with .git directory within theirs worktrees) with commondir can be of tremendous help. For example, commondir link can be used to avoid duplication of objects and also to keep branches in sync with multiple copies of the repo's worktree, while keeping the .git directory inside the worktree can be (ab?-)used to exploit the sharing of the same submodule worktree across different projects (this at least works on Windows with submodule directory being a directory junction, but having a junction is not relevant for reproducing the bug described below). Unfortunately, after the addition of the check for the new config option, when `git status` is run in the root repo of such a setup, it gives an output akin to this: ```sh fatal: unable to access '�??\1?/config': Invalid argument fatal: 'git status --porcelain=2' failed in submodule commonlibs ``` where `�??\1?` part of '�??\1?/config' varies from run to run, and `commonlibs` is the name of submodule's directory. Currently, when Git discovers old-style submodule , it spawns subprocess to get its status, like this one: ```sh cd commonlibs; unset GIT_PREFIX; GIT_DIR=.git git status --porcelain=2 ``` Unsurprisingly, the following output is also quite unexpected: ``` fatal: unable to access '`??L&?/config': Invalid argument ``` The core reason for these is that global repository field for commondir is not being cleared to `NULL` after being `free()`'d in `repo_set_commondir()`, which is precisely what this commit fixes. Regarding the further details of the case of investigation, this value of struct pointed by the global `the_repository` pointer is checked for being not-NULL down in the callstack in compatibility layer for MinGW in a function that is called by `repo_set_commondir()` before the `free()`'d value gets assigned in its body (i.e. the body of `repo_set_commondir()`). Backtrace from the check is: ``` at compat/mingw.c:784 path=0x ".git/commondir", hint=0) at strbuf.c:758 gitdir=0x ".git") at setup.c:313 commondir=0x0) at repository.c:57 root=0x ".git", o=0x) at repository.c:76 at environment.c:179 at environment.c:334 old_cwd=0x "C:/Users/%username%//commonlibs", new_cwd=0x "C:/Users/%username%//commonlibs", data=0x0) at environment.c:348 new_cwd=0x "C:/Users/%username%//commonlibs") at chdir-notify.c:72 argc=2, argv=0x) at git.c:458 at git.c:721 at git.c:788 at common-main.c:56 ``` Backtrace from the death is: ``` at usage.c:210 path=0x "`\001\r��\004/config", mode=4, flag=0) at wrapper.c:667 fn=0x , data=0x) at config.c:2142 fn=0x , data=0x, config_source=0x0, opts=0x) at config.c:2198 at config.c:2524 repo=0x ) at config.c:2543 repo=0x , key=0x "windows.appendatomically", dest=0x ) at config.c:2612 key=0x "windows.appendatomically", dest=0x ) at config.c:2714 filename=0x ".git/commondir", oflags=0) at compat/mingw.c:785 path=0x ".git/commondir", hint=0) at strbuf.c:758 gitdir=0x ".git") at setup.c:313 commondir=0x0) at repository.c:57 root=0x ".git", o=0x) at repository.c:76 at environment.c:179 at environment.c:334 old_cwd=0x "C:/Users/%username%//commonlibs", new_cwd=0x "C:/Users/%username%//commonlibs", data=0x0) at environment.c:348 new_cwd=0x "C:/Users/%username%//commonlibs") at chdir-notify.c:72 argc=2, argv=0x) at git.c:458 at git.c:721 at git.c:788 at common-main.c:56 ``` Co-Authored-By: Johannes Schindelin Co-Authored-By: Andrey Zabavnikov Signed-off-by: 孙卓识 Signed-off-by: Johannes Schindelin Signed-off-by: Andrey Zabavnikov --- repository.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repository.c b/repository.c index 5d166b692c8aa8..a2e1b89e14d979 100644 --- a/repository.c +++ b/repository.c @@ -46,7 +46,7 @@ static void repo_set_commondir(struct repository *repo, { struct strbuf sb = STRBUF_INIT; - free(repo->commondir); + FREE_AND_NULL(repo->commondir); if (commondir) { repo->different_commondir = 1;