Skip to content

Commit

Permalink
Fix status for old-style submodules with commondir
Browse files Browse the repository at this point in the history
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 this bug).

Unfortunately, at the moment, when `git status` is run in the root repo
of such a setup, it gives an output akin to this:
```sh
$ git status
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:
```
$ GIT_DIR=.git git -C commonlibs/ status --porcelain=2
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

Signed-off-by: Andrey Zabavnikov <zabavnikov@gmail.com>
  • Loading branch information
sceptical-coder committed Oct 30, 2022
1 parent bb3e903 commit 55563c7
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 55563c7

Please sign in to comment.