forked from git/git
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit 4ae630e
committed
Fix status for old-style submodules with commondir
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, at the moment, 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:
```
#0 mingw_open (filename=0x<address-25> ".git/commondir", oflags=0)
at compat/mingw.c:784
#1 0x<address-27> in strbuf_read_file (sb=0x<address-26>,
path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
#2 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
gitdir=0x<address-22> ".git") at setup.c:313
#3 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
commondir=0x0) at repository.c:57
#4 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
#5 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
at environment.c:179
#6 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
at environment.c:334
#7 0x<address-14> in update_relative_gitdir (name=0x0,
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
#8 0x<address-12> in chdir_notify (
new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
#9 0x<address-10> in setup_work_tree () at setup.c:428
#10 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
argc=2, argv=0x<address-2>) at git.c:458
#11 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
at git.c:721
#12 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
at git.c:788
#13 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
#14 0x<address-1> in main (argc=6, argv=0x<address-0>)
at common-main.c:56
```
Backtrace from the death is:
```
#0 die_errno (fmt=0x<address-42> <result_type+2002> "unable to access '%s'")
at usage.c:210
#1 0x<address-41> in access_or_die (
path=0x<address-40> "`\001\r��\004/config", mode=4, flag=0)
at wrapper.c:667
#2 0x<address-39> in do_git_config_sequence (opts=0x<address-35>,
fn=0x<address-37> <git_config_include>, data=0x<address-36>)
at config.c:2142
#3 0x<address-38> in config_with_options (
fn=0x<address-37> <git_config_include>, data=0x<address-36>,
config_source=0x0, opts=0x<address-35>) at config.c:2198
#4 0x<address-34> in repo_read_config (repo=0x<address-19> <the_repo>)
at config.c:2524
#5 0x<address-33> in git_config_check_init (
repo=0x<address-19> <the_repo>) at config.c:2543
#6 0x<address-32> in repo_config_get_bool (
repo=0x<address-19> <the_repo>,
key=0x<address-30> <pad+3116> "windows.appendatomically",
dest=0x<address-29> <append_atomically>) at config.c:2612
#7 0x<address-31> in git_config_get_bool (
key=0x<address-30> <pad+3116> "windows.appendatomically",
dest=0x<address-29> <append_atomically>) at config.c:2714
#8 0x<address-28> in mingw_open (
filename=0x<address-25> ".git/commondir", oflags=0) at compat/mingw.c:785
#9 0x<address-27> in strbuf_read_file (sb=0x<address-26>,
path=0x<address-25> ".git/commondir", hint=0) at strbuf.c:758
#10 0x<address-24> in get_common_dir_noenv (sb=0x<address-23>,
gitdir=0x<address-22> ".git") at setup.c:313
#11 0x<address-21> in repo_set_commondir (repo=0x<address-19> <the_repo>,
commondir=0x0) at repository.c:57
#12 0x<address-20> in repo_set_gitdir (repo=0x<address-19> <the_repo>,
root=0x<address-15> ".git", o=0x<address-18>) at repository.c:76
#13 0x<address-17> in setup_git_env (git_dir=0x<address-15> ".git")
at environment.c:179
#14 0x<address-16> in set_git_dir_1 (path=0x<address-15> ".git")
at environment.c:334
#15 0x<address-14> in update_relative_gitdir (name=0x0,
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
#16 0x<address-12> in chdir_notify (
new_cwd=0x<address-11> "C:/Users/%username%/<root-repo-name>/commonlibs") at chdir-notify.c:72
#17 0x<address-10> in setup_work_tree () at setup.c:428
#18 0x<address-9> in run_builtin (p=0x<address-8> <commands+2856>,
argc=2, argv=0x<address-2>) at git.c:458
#19 0x<address-7> in handle_builtin (argc=2, argv=0x<address-2>)
at git.c:721
#20 0x<address-6> in run_argv (argcp=0x<address-5>, argv=0x<address-4>)
at git.c:788
#21 0x<address-3> in cmd_main (argc=2, argv=0x<address-2>) at git.c:921
#22 0x<address-1> in main (argc=6, argv=0x<address-0>)
at common-main.c:56
```
Signed-off-by: Andrey Zabavnikov <[email protected]>1 parent be88dd9 commit 4ae630eCopy full SHA for 4ae630e
1 file changed
+1
-1
lines changed+1-1
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
46 | 46 |
| |
47 | 47 |
| |
48 | 48 |
| |
49 |
| - | |
| 49 | + | |
50 | 50 |
| |
51 | 51 |
| |
52 | 52 |
| |
|
0 commit comments