Skip to content

Commit

Permalink
amend! Add config option windows.appendAtomically
Browse files Browse the repository at this point in the history
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<address-25> ".git/commondir", hint=0) at strbuf.c:758
    gitdir=0x<address-22> ".git") at setup.c:313
    commondir=0x0) at repository.c:57
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
    at environment.c:179
    at environment.c:334
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
    argc=2, argv=0x<address-2>) 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<address-40> "`\001\r��\004/config", mode=4, flag=0)
    at wrapper.c:667
    fn=0x<address-37> <git_config_include>, data=0x<address-36>)
    at config.c:2142
    fn=0x<address-37> <git_config_include>, data=0x<address-36>,
    config_source=0x0, opts=0x<address-35>) at config.c:2198
    at config.c:2524
    repo=0x<address-19> <the_repo>) at config.c:2543
    repo=0x<address-19> <the_repo>,
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2612
    key=0x<address-30> <pad+3116> "windows.appendatomically",
    dest=0x<address-29> <append_atomically>) at config.c:2714
    filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
    path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
    gitdir=0x<address-22> ".git") at setup.c:313
    commondir=0x0) at repository.c:57
    root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
    at environment.c:179
    at environment.c:334
    old_cwd=0x<address-13> "C:/Users/%username%/<root-repo-name>/commonlibs",
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs", data=0x0) at environment.c:348
    new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
    argc=2, argv=0x<address-2>) at git.c:458
    at git.c:721
    at git.c:788
    at common-main.c:56
```

Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de>
Co-Authored-By: Andrey Zabavnikov <zabavnikov@gmail.com>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Andrey Zabavnikov <zabavnikov@gmail.com>
  • Loading branch information
sceptical-coder and dscho committed Nov 3, 2022
1 parent be88dd9 commit df38aa7
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit df38aa7

Please sign in to comment.