submodule embedgitdirs
v6 cover submodule embedgitdirs
v6:
* renamed embedgitdirs to absorbgitdirs embedding may be interpreted as embedding the git dir into the working directory, whereas absorbing sounds more like the submodule is absorbed by the superproject, making the submodule less independent
* Worktrees API offer uses_worktrees(void) and submodule_uses_worktree(path).
* moved the printing to stderr and one layer up (out of the pure relocate_git_dir function).
* connect_... is in dir.h now.
v5:
* Add another layer of abstraction, i.e. the relocate_git_dir is only about moving a git dir of one repository. The submodule specific stuff (e.g. recursion into nested submodules) is in submodule.{c,h}
This was motivated by reviews on the series of checkout aware of submodules building on top of this series, as we want to directly call the embed-git-dirs function without the overhead of spawning a child process.
v4:
* rebuilt on top of nd/worktree-list-fixup
* fix and test behavior for un-init submodules (don't crash, rather do nothing)
* incorporated a "static" as pointed out by Ramsay
* use internal functions instead of duplicating code in worktree.c (use get_common_dir_noenv for the submodule to actually get the common dir)
* fixed a memory leak in relocate_gitdir
v3:
* have a slightly more generic function "relocate_gitdir". The recursion is strictly related to submodules, though.
* bail out if a submodule is using worktrees.
This also lays the groundwork for later doing the proper thing, as worktree.h offers a function get_submodule_worktrees(path)
* nit by duy: use git_path instead of git_common_dir
v2:
* fixed commit message for patch:
"submodule: use absolute path for computing relative path connecting"
* a new patch "submodule helper: support super prefix"
* redid the final patch with more tests and fixing bugs along the way
* "test-lib-functions.sh: teach test_commit -C <dir>" unchanged
v1:
The discussion of the submodule checkout series revealed to me that a command is needed to move the git directory from the submodules working tree to be embedded into the superprojects git directory.
So I wrote the code to intern the submodules git dir into the superproject, but whilst writing the code I realized this could be valueable for our use in testing too. So I exposed it via the submodule--helper. But as the submodule helper ought to be just an internal API, we could also offer it via the proper submodule command.
The command as it is has little value to the end user for now, but breaking it out of the submodule checkout series hopefully makes review easier.
Thanks,
Stefan
Stefan Beller (7):
submodule: use absolute path for computing relative path connecting submodule helper: support super prefix test-lib-functions.sh: teach test_commit -C <dir>
worktree: get worktrees from submodules
worktree: add function to check if worktrees are in use move connect_work_tree_and_git_dir to dir.h
submodule: add absorb-git-dir function
Documentation/git-submodule.txt | 15 +++++ builtin/submodule--helper.c | 69 ++++++++++++++++---- dir.c | 38 +++++++++++ dir.h | 4 ++ git-submodule.sh | 7 +- git.c | 2 +- submodule.c | 127 ++++++++++++++++++++++++++++++------- submodule.h | 5 +- t/t7412-submodule-absorbgitdirs.sh | 101 +++++++++++++++++++++++++++++ t/test-lib-functions.sh | 20 ++++-- worktree.c | 70 +++++++++++++++++--- worktree.h | 13 ++++ 12 files changed, 418 insertions(+), 53 deletions(-) create mode 100755 t/t7412-submodule-absorbgitdirs.sh
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
PATCH v6 1/7 submodule: use absolute path for computing relative path connecting
The current caller of connect_work_tree_and_git_dir passes
an absolute path for the git_dir parameter. In the future patch we will also pass in relative path for git_dir. Extend the functionality of connect_work_tree_and_git_dir to take relative paths for parameters.
We could work around this in the future patch by computing the absolute path for the git_dir in the calling site, however accepting relative paths for either parameter makes the API for this function much harder to misuse.
--- submodule.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
submodule.c +7 -5
@@ -1227,23 +1227,25 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) {struct strbuf file_name =STRBUF_INIT ;struct strbuf rel_path =STRBUF_INIT ; -const char *real_work_tree =xstrdup (real_path (work_tree)); +char *real_git_dir =xstrdup (real_path (git_dir)); +char *real_work_tree =xstrdup (real_path (work_tree));/* Update gitfile */ strbuf_addf (&file_name,"%s/.git" , work_tree);write_file (file_name.buf,"gitdir: %s" , -relative_path (git_dir, real_work_tree, &rel_path)); +relative_path (real_git_dir, real_work_tree, &rel_path));/* Update core.worktree setting */ strbuf_reset (&file_name); -strbuf_addf (&file_name,"%s/config" , git_dir); +strbuf_addf (&file_name,"%s/config" , real_git_dir);git_config_set_in_file (file_name.buf,"core.worktree" , -relative_path (real_work_tree, git_dir, +relative_path (real_work_tree, real_git_dir, &rel_path));strbuf_release (&file_name);strbuf_release (&rel_path); -free ((void *)real_work_tree); +free (real_work_tree); +free (real_git_dir); }int parallel_submodules (void )
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
Re: [PATCHv6 1/7] submodule: use absolute path for computing relative path connecting
Quoted 21 lines · Stefan Beller
The current caller of
connect_work_tree_and_git_dirpasses
an absolute path for thegit_dirparameter. In the future patch we will also pass in relative path forgit_dir. Extend the functionality ofconnect_work_tree_and_git_dirto take relative paths for parameters.We could work around this in the future patch by computing the absolute path for the
git_dirin the calling site, however accepting relative paths for either parameter makes the API for this function much harder to misuse.Signed-off-by Stefan Beller <[email protected]>Signed-off-by Junio C Hamano <[email protected]>--- submodule.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)submodule.c +0
-0
submodule.c void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) · line 1230
Quoted 5 lines
submodule.c +1
-1@@ -1227,23 +1227,25 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) {struct strbuf file_name =STRBUF_INIT ;struct strbuf rel_path =STRBUF_INIT ; -const char *real_work_tree =xstrdup (real_path (work_tree)); +char *real_git_dir =xstrdup (real_path (git_dir));
Is it a bad idea to rename the argument git_dir to git_dir_input, or something, then have a new "git_dir" variable here? It certainly helps reduce diff size, but not sure if the end result looks better or worse.
Quoted 28 lines
submodule.c +6
-5+char *real_work_tree =xstrdup (real_path (work_tree));/* Update gitfile */ strbuf_addf (&file_name,"%s/.git" , work_tree);write_file (file_name.buf,"gitdir: %s" , -relative_path (git_dir, real_work_tree, &rel_path)); +relative_path (real_git_dir, real_work_tree, &rel_path));/* Update core.worktree setting */ strbuf_reset (&file_name); -strbuf_addf (&file_name,"%s/config" , git_dir); +strbuf_addf (&file_name,"%s/config" , real_git_dir);git_config_set_in_file (file_name.buf,"core.worktree" , -relative_path (real_work_tree, git_dir, +relative_path (real_work_tree, real_git_dir, &rel_path));strbuf_release (&file_name);strbuf_release (&rel_path); -free ((void *)real_work_tree); +free (real_work_tree); +free (real_git_dir); }int parallel_submodules (void ) --2.11.0.rc2.30.gc512cbd.dirty
Signature · 1 line
Duy
PATCH v6 2/7 submodule helper: support super prefix
In reply to Stefan BellerJust like main commands in Git, the submodule helper needs access to the superproject prefix. Enable this in the git.c but have its own fuse in the helper code by having a flag to turn on the super prefix.
--- builtin/submodule--helper.c | 31 ++++++++++++++++++++----------- git.c | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-)
builtin/submodule--helper.c +20 -11
@@ -1076,21 +1076,24 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,return 0 ; } +#define SUPPORT_SUPER_PREFIX (1<<0) +struct cmd_struct {const char *cmd;int (*fn)(int ,const char **,const char *); +int option; };static struct cmd_struct commands[] = { - {"list" , module_list}, - {"name" , module_name}, - {"clone" , module_clone}, - {"update-clone" , update_clone}, - {"relative-path" , resolve_relative_path}, - {"resolve-relative-url" , resolve_relative_url}, - {"resolve-relative-url-test" , resolve_relative_url_test}, - {"init" , module_init}, - {"remote-branch" , resolve_remote_submodule_branch} + {"list" , module_list,0 }, + {"name" , module_name,0 }, + {"clone" , module_clone,0 }, + {"update-clone" , update_clone,0 }, + {"relative-path" , resolve_relative_path,0 }, + {"resolve-relative-url" , resolve_relative_url,0 }, + {"resolve-relative-url-test" , resolve_relative_url_test,0 }, + {"init" , module_init,0 }, + {"remote-branch" , resolve_remote_submodule_branch,0 }, };int cmd_submodule__helper (int argc,const char **argv,const char *prefix)
@@ -1100,9 +1103,15 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)die (_ ("submodule--helper subcommand must be " "called with a subcommand" )); -for (i =0 ; i <ARRAY_SIZE (commands); i++) -if (!strcmp (argv[1 ], commands[i].cmd)) +for (i =0 ; i <ARRAY_SIZE (commands); i++) { +if (!strcmp (argv[1 ], commands[i].cmd)) { +if (get_super_prefix () && + !(commands[i].option &SUPPORT_SUPER_PREFIX )) +die ("%s doesn't support --super-prefix" , + commands[i].cmd);return commands[i].fn (argc -1 , argv +1 , prefix); + } + }die (_ ("'%s' is not a valid submodule--helper " "subcommand" ), argv[1 ]);
git.c +1 -1
@@ -493,7 +493,7 @@ static struct cmd_struct commands[] = { { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE }, { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE }, { "stripspace", cmd_stripspace }, - { "submodule--helper", cmd_submodule__helper, RUN_SETUP }, + { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX}, { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP }, { "tag", cmd_tag, RUN_SETUP }, { "unpack-file", cmd_unpack_file, RUN_SETUP },
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
Re: [PATCHv6 2/7] submodule helper: support super prefix
Quoted 17 lines · Stefan Beller
Just like main commands in Git, the submodule helper needs access to the superproject prefix. Enable this in the
git.cbut have its own fuse in the helper code by having a flag to turn on the super prefix.Signed-off-by Stefan Beller <[email protected]>Signed-off-by Junio C Hamano <[email protected]>--- builtin/submodule--helper.c | 31 ++++++++++++++++++++----------- git.c | 2 +- 2 files changed, 21 insertions(+), 12 deletions(-)builtin/submodule--helper.c +0
-0
builtin/submodule--helper.c static int resolve_remote_submodule_branch(int argc, const char **argv, · line 1084
Quoted 9 lines
builtin/submodule--helper.c +3
-0@@ -1076,21 +1076,24 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,return 0 ; } +#define SUPPORT_SUPER_PREFIX (1<<0) +struct cmd_struct {const char *cmd;int (*fn)(int ,const char **,const char *); +int option;
unsigned int is probably safer for variables that are used as bit-flags.
builtin/submodule--helper.c int cmd_submodule__helper(int argc, const char **argv, const char *prefix) · line 1111
Quoted 13 lines
builtin/submodule--helper.c +6
-2int cmd_submodule__helper (int argc,const char **argv,const char *prefix)@@ -1100,9 +1103,15 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)die (_ ("submodule--helper subcommand must be " "called with a subcommand" )); -for (i =0 ; i <ARRAY_SIZE (commands); i++) -if (!strcmp (argv[1 ], commands[i].cmd)) +for (i =0 ; i <ARRAY_SIZE (commands); i++) { +if (!strcmp (argv[1 ], commands[i].cmd)) { +if (get_super_prefix () && + !(commands[i].option &SUPPORT_SUPER_PREFIX )) +die ("%s doesn't support --super-prefix" , + commands[i].cmd);
If it's meant for users to see, please _() the string.
Quoted 11 lines
builtin/submodule--helper.c +2
-0return commands[i].fn (argc -1 , argv +1 , prefix); + } + }die (_ ("'%s' is not a valid submodule--helper " "subcommand" ), argv[1 ]);git.c +0
-0
git.c static struct cmd_struct commands[] = { · line 496
Quoted 5 lines
git.c +1
-1@@ -493,7 +493,7 @@ static struct cmd_struct commands[] = { { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE }, { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE }, { "stripspace", cmd_stripspace }, - { "submodule--helper", cmd_submodule__helper, RUN_SETUP }, + { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX},
The same macro defined twice in two separate .c files? Hmm.. it confused me a bit because i thought there was a connection.. I guess it's ok.
Signature · 1 line
Duy
Re: [PATCHv6 2/7] submodule helper: support super prefix
Quoted 2 lines
unsigned int is probably safer for variables that are used as bit-flags.
done
Quoted 1 line
If it's meant for users to see, please
_()the string.
done
Quoted 5 lines
Quoted 1 line
+ { "submodule--helper",
cmd_submodule__helper,RUN_SETUP|SUPPORT_SUPER_PREFIX},The same macro defined twice in two separate .c files? Hmm.. it confused me a bit because i thought there was a connection.. I guess it's ok.
Its effect is exactly the same. just plain code duplication. I assume that is okay here as it really is only one constant for now. Maybe we can refactor that to
be defined in a header file (but which? There is no such thing as a git.h, where I'd expect to put it.)
Thanks,
Stefan
PATCH v6 3/7 test-lib-functions.sh: teach test_commit -C <dir>
In reply to Stefan BellerSpecifically when setting up submodule tests, it comes in handy if we can create commits in repositories that are not at the root of the tested trash dir. Add "-C <dir>" similar to gits -C parameter that will perform the operation in the given directory.
--- t/test-lib-functions.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
t/test-lib-functions.sh +15 -5
@@ -157,16 +157,21 @@ debug () { GIT_TEST_GDB=1 "$@" } -# Call test_commit with the arguments "<message> [<file> [<contents> [<tag>]]]" +# Call test_commit with the arguments +# [-C <directory>] <message> [<file> [<contents> [<tag>]]]" # # This will commit a file with the given contents and the given commit # message, and tag the resulting commit with the given tag name. # # <file>, <contents>, and <tag> all default to <message>. +# +# If the first argument is "-C", the second argument is used as a path for +# the git invocations. test_commit () { notick= && signoff= && + indir= && while test $# != 0 do case "$1" in
@@ -176,21 +181,26 @@ test_commit () { --signoff) signoff="$1" ;; + -C) + indir="$2" + shift + ;; *) break ;; esac shift done && + indir=${indir:+"$indir"/} && file=${2:-"$1.t"} && - echo "${3-$1}" > "$file" && - git add "$file" && + echo "${3-$1}" > "$indir$file" && + git ${indir:+ -C "$indir"} add "$file" && if test -z "$notick" then test_tick fi && - git commit $signoff -m "$1" && - git tag "${4:-$1}" + git ${indir:+ -C "$indir"} commit $signoff -m "$1" && + git ${indir:+ -C "$indir"} tag "${4:-$1}" } # Call test_merge with the arguments "<message> <commit>", where <commit>
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
PATCH v6 4/7 worktree: get worktrees from submodules
In reply to Stefan BellerIn a later patch we want to move around the the git directory of a submodule. Both submodules as well as worktrees are involved in placing git directories at unusual places, so their functionality may collide. To react appropriately to situations where worktrees in submodules are in use, offer a new function to query the worktrees for submodules.
--- worktree.c | 46 ++++++++++++++++++++++++++++++++++++---------- worktree.h | 6 ++++++ 2 files changed, 42 insertions(+), 10 deletions(-)
worktree.c +36 -10
@@ -72,7 +72,7 @@ static void add_head_info(struct strbuf *head_ref, struct worktree *worktree)/** * get the main worktree */ -static struct worktree *get_main_worktree (void ) +static struct worktree *get_main_worktree (const char *git_common_dir) {struct worktree *worktree =NULL ;struct strbuf path =STRBUF_INIT ;
@@ -81,12 +81,12 @@ static struct worktree *get_main_worktree(void)int is_bare =0 ;int is_detached =0 ; -strbuf_add_absolute_path (&worktree_path,get_git_common_dir ()); +strbuf_add_absolute_path (&worktree_path, git_common_dir); is_bare = !strbuf_strip_suffix (&worktree_path,"/.git" );if (is_bare)strbuf_strip_suffix (&worktree_path,"/." ); -strbuf_addf (&path,"%s/HEAD" ,get_git_common_dir ()); +strbuf_addf (&path,"%s/HEAD" , git_common_dir); worktree =xcalloc (1 ,sizeof (*worktree)); worktree->path =strbuf_detach (&worktree_path,NULL );
@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)return worktree; } -static struct worktree *get_linked_worktree (const char *id) +static struct worktree *get_linked_worktree (const char *git_common_dir, +const char *id) {struct worktree *worktree =NULL ;struct strbuf path =STRBUF_INIT ;
@@ -112,7 +113,7 @@ static struct worktree *get_linked_worktree(const char *id)if (!id)die ("Missing linked worktree name" ); -strbuf_git_common_path (&path,"worktrees/%s/gitdir" , id); +strbuf_addf (&path,"%s/worktrees/%s/gitdir" , git_common_dir, id);if (strbuf_read_file (&worktree_path, path.buf,0 ) <=0 )/* invalid gitdir file */ goto done;
@@ -125,7 +126,7 @@ static struct worktree *get_linked_worktree(const char *id) }strbuf_reset (&path); -strbuf_addf (&path,"%s/worktrees/%s/HEAD" ,get_git_common_dir (), id); +strbuf_addf (&path,"%s/worktrees/%s/HEAD" , git_common_dir, id);if (parse_ref (path.buf, &head_ref, &is_detached) <0 ) goto done;
@@ -167,7 +168,8 @@ static int compare_worktree(const void *a_, const void *b_)return fspathcmp ((*a)->path, (*b)->path); } -struct worktree **get_worktrees (unsigned flags) +static struct worktree **get_worktrees_internal (const char *git_common_dir, +unsigned flags) {struct worktree **list =NULL ;struct strbuf path =STRBUF_INIT ;
@@ -177,9 +179,9 @@ struct worktree **get_worktrees(unsigned flags) list =xmalloc (alloc *sizeof (struct worktree *)); - list[counter++] =get_main_worktree (); + list[counter++] =get_main_worktree (git_common_dir); -strbuf_addf (&path,"%s/worktrees" ,get_git_common_dir ()); +strbuf_addf (&path,"%s/worktrees" , git_common_dir); dir =opendir (path.buf);strbuf_release (&path);if (dir) {
@@ -188,7 +190,7 @@ struct worktree **get_worktrees(unsigned flags)if (is_dot_or_dotdot (d->d_name))continue ; -if ((linked =get_linked_worktree (d->d_name))) { +if ((linked =get_linked_worktree (git_common_dir, d->d_name))) {ALLOC_GROW (list, counter +1 , alloc); list[counter++] = linked; }
@@ -209,6 +211,30 @@ struct worktree **get_worktrees(unsigned flags)return list; } +struct worktree **get_worktrees (unsigned flags) +{ +return get_worktrees_internal (get_git_common_dir (), flags); +} + +struct worktree **get_submodule_worktrees (const char *path,unsigned flags) +{ +char *submodule_gitdir; +struct strbuf sb =STRBUF_INIT ; +struct worktree **ret; + + submodule_gitdir =git_pathdup_submodule (path,"%s" ,"" ); +if (!submodule_gitdir) +return NULL ; + +/* the env would be set for the superproject */ +get_common_dir_noenv (&sb, submodule_gitdir); + ret =get_worktrees_internal (sb.buf, flags); + +strbuf_release (&sb); +free (submodule_gitdir); +return ret; +} +const char *get_worktree_git_dir (const struct worktree *wt) {if (!wt)
worktree.h +6 -0
@@ -27,6 +27,12 @@ struct worktree {*/ extern struct worktree **get_worktrees (unsigned flags); +/* +* Get the worktrees of a submodule named by `path`. +*/ +extern struct worktree **get_submodule_worktrees (const char *path, +unsigned flags); +/* * Return git dir of the worktree. Note that the path may be relative. * If wt is NULL, git dir of current worktree is returned.
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
Re: [PATCHv6 4/7] worktree: get worktrees from submodules
Review static struct worktree *get_main_worktree(void)
Quoted 4 lines · Stefan Beller
worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL);(quoted diff) +0
-0@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)
All the good stuff is outside context lines again.. Somewhere between here we call add_head_info() which calls resolve_ref_unsafe(), which always uses data from current repo, not the submodule we want it to look at.
worktree.c static int compare_worktree(const void *a_, const void *b_) · line 168
Quoted 2 lines
worktree.c +0
-0@@ -167,7 +168,8 @@ static int compare_worktree(const void *a_, const void *b_)return fspathcmp ((*a)->path, (*b)->path);
fspathcmp() reads core.ignorecase from current repo. I guess it's insane to have this key different between repos on the same machine, so it should be ok. But I want to point this out just in case I'm missing something.
worktree.c struct worktree **get_worktrees(unsigned flags) · line 211
Quoted 11 lines
worktree.c +1
-1@@ -188,7 +190,7 @@ struct worktree **get_worktrees(unsigned flags)if (is_dot_or_dotdot (d->d_name))continue ; -if ((linked =get_linked_worktree (d->d_name))) { +if ((linked =get_linked_worktree (git_common_dir, d->d_name))) {ALLOC_GROW (list, counter +1 , alloc); list[counter++] = linked; }@@ -209,6 +211,30 @@ struct worktree **get_worktrees(unsigned flags)return list;
Right before this line is mark_current_worktree(), which in turn calls get_git_dir() and not suitable for peeking into another repository the way submodule code does. get_worktree_git_dir() called within that function shares the same problem.
Quoted 9 lines
worktree.c +7
-0} +struct worktree **get_worktrees (unsigned flags) +{ +return get_worktrees_internal (get_git_common_dir (), flags); +} + +struct worktree **get_submodule_worktrees (const char *path,unsigned flags) +{
worktree.c struct worktree **get_worktrees(unsigned flags) · line 230
Quoted 10 lines
worktree.c +10
-0+char *submodule_gitdir; +struct strbuf sb =STRBUF_INIT ; +struct worktree **ret; + + submodule_gitdir =git_pathdup_submodule (path,"%s" ,"" ); +if (!submodule_gitdir) +return NULL ; + +/* the env would be set for the superproject */ +get_common_dir_noenv (&sb, submodule_gitdir);
Technically we need to read submodule_gitdir/.config and see if we can understand core.repositoryformatversion, or find any unrecognized extensions. But the problem is not specific to this code. And fixing it is no small task. But perhaps we could call a dummy validate_submodule_gitdir() here? Then when we implement that function for real, we don't have to search the entire code base to see where to put it.
Kinda off-topic though. Feel free to ignore the above comment.
Quoted 6 lines
worktree.c +6
-0+ ret =get_worktrees_internal (sb.buf, flags); + +strbuf_release (&sb); +free (submodule_gitdir); +return ret; +}
Signature · 1 line
Duy
Re: [PATCHv6 4/7] worktree: get worktrees from submodules
Quoted 10 lines · Duy Nguyen
Review static struct worktree *get_main_worktree(void)
Quoted 4 lines · Stefan Beller
worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL);(quoted diff) +0
-0@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)All the good stuff is outside context lines again.. Somewhere between here we call
add_head_info()which callsresolve_ref_unsafe(), which always uses data from current repo, not the submodule we want it to look at.
Unrelated side question: What would you think of "variable context line configuration" ? e.g. you could configure it to include anything from up that line
that is currently shown after the @@ which is the function signature line.
As to the add_head_info/resolve_ref_unsafe what impact does that have? It produces a wrong head info but AFAICT it will never die(), such that for the purposes of this series (which only wants to know if a submodule uses the worktree feature) it should be fine.
It is highly misleading though for others to build upon this. So maybe I'll only add the functionality internally in worktree.c and document why the values are wrong, and only expose the "int submodule_uses_worktrees(const char *path)" ?
Quoted 7 lines
worktree.c struct worktree **get_worktrees(unsigned flags) · line 211
Quoted 2 lines
worktree.c +0
-0@@ -209,6 +211,30 @@ struct worktree **get_worktrees(unsigned flags)return list;Right before this line is
mark_current_worktree(), which in turn callsget_git_dir()and not suitable for peeking into another repository the way submodule code does.get_worktree_git_dir()called within that function shares the same problem.
It actually works correctly: "No submodule is the current worktree".
Quoted 29 lines
Quoted 10 lines
worktree.c +7
-0} +struct worktree **get_worktrees (unsigned flags) +{ +return get_worktrees_internal (get_git_common_dir (), flags); +} + +struct worktree **get_submodule_worktrees (const char *path,unsigned flags) +{worktree.c struct worktree **get_worktrees(unsigned flags) · line 230
Quoted 10 lines
worktree.c +10
-0+char *submodule_gitdir; +struct strbuf sb =STRBUF_INIT ; +struct worktree **ret; + + submodule_gitdir =git_pathdup_submodule (path,"%s" ,"" ); +if (!submodule_gitdir) +return NULL ; + +/* the env would be set for the superproject */ +get_common_dir_noenv (&sb, submodule_gitdir);Technically we need to read submodule_gitdir/.config and see if we can understand core.repositoryformatversion, or find any unrecognized extensions. But the problem is not specific to this code. And fixing it is no small task. But perhaps we could call a dummy
validate_submodule_gitdir()here? Then when we implement that function for real, we don't have to search the entire code base to see where to put it.
Quoted 1 line
Kinda off-topic though. Feel free to ignore the above comment.
ok I'll add a TODO/emptyfunction for that.
Thanks for the review!
Stefan
Re: [PATCHv6 4/7] worktree: get worktrees from submodules
Quoted 12 lines · Stefan Beller
Quoted 10 lines · Duy Nguyen
Review static struct worktree *get_main_worktree(void)
Quoted 4 lines · Stefan Beller
worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL);(quoted diff) +0
-0@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)All the good stuff is outside context lines again.. Somewhere between here we call
add_head_info()which callsresolve_ref_unsafe(), which always uses data from current repo, not the submodule we want it to look at.
Quoted 4 lines
Unrelated side question: What would you think of "variable context line configuration" ? e.g. you could configure it to include anything from up that line
that is currently shown after the @@ which is the function signature line.
Hmm.. no idea. I once dreamt of writing "Diff-Options: -U10" in the commit message and let git-log and everybody use that option automatically, though. I guess it's unrelated to your question :D
Quoted 9 lines
As to the add_head_info/resolve_ref_unsafe what impact does that have? It produces a wrong head info but AFAICT it will never
die(), such that for the purposes of this series (which only wants to know if a submodule uses the worktree feature) it should be fine.It is highly misleading though for others to build upon this. So maybe I'll only add the functionality internally in
worktree.cand document why the values are wrong, and only expose the "intsubmodule_uses_worktrees(const char *path)" ?
Yeah for submodule use then it should be ok. But people may start using it for something else, not realizing that it does not work as expected.
Signature · 1 line
Duy
Re: [PATCHv6 4/7] worktree: get worktrees from submodules
In reply to Stefan BellerQuoted 67 lines · Stefan Beller
Quoted 10 lines · Duy Nguyen
Review static struct worktree *get_main_worktree(void)
Quoted 4 lines · Stefan Beller
worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL);(quoted diff) +0
-0@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)All the good stuff is outside context lines again.. Somewhere between here we call
add_head_info()which callsresolve_ref_unsafe(), which always uses data from current repo, not the submodule we want it to look at.Unrelated side question: What would you think of "variable context line configuration" ? e.g. you could configure it to include anything from up that line
that is currently shown after the @@ which is the function signature line.As to the add_head_info/resolve_ref_unsafe what impact does that have? It produces a wrong head info but AFAICT it will never
die(), such that for the purposes of this series (which only wants to know if a submodule uses the worktree feature) it should be fine.It is highly misleading though for others to build upon this. So maybe I'll only add the functionality internally in
worktree.cand document why the values are wrong, and only expose the "intsubmodule_uses_worktrees(const char *path)" ?Quoted 7 lines
worktree.c struct worktree **get_worktrees(unsigned flags) · line 211
Quoted 2 lines
worktree.c +0
-0@@ -209,6 +211,30 @@ struct worktree **get_worktrees(unsigned flags)return list;Right before this line is
mark_current_worktree(), which in turn callsget_git_dir()and not suitable for peeking into another repository the way submodule code does.get_worktree_git_dir()called within that function shares the same problem.It actually works correctly: "No submodule is the current worktree".
Quoted 29 lines
Quoted 10 lines
worktree.c +7
-0} +struct worktree **get_worktrees (unsigned flags) +{ +return get_worktrees_internal (get_git_common_dir (), flags); +} + +struct worktree **get_submodule_worktrees (const char *path,unsigned flags) +{worktree.c struct worktree **get_worktrees(unsigned flags) · line 230
Quoted 10 lines
worktree.c +10
-0+char *submodule_gitdir; +struct strbuf sb =STRBUF_INIT ; +struct worktree **ret; + + submodule_gitdir =git_pathdup_submodule (path,"%s" ,"" ); +if (!submodule_gitdir) +return NULL ; + +/* the env would be set for the superproject */ +get_common_dir_noenv (&sb, submodule_gitdir);Technically we need to read submodule_gitdir/.config and see if we can understand core.repositoryformatversion, or find any unrecognized extensions. But the problem is not specific to this code. And fixing it is no small task. But perhaps we could call a dummy
validate_submodule_gitdir()here? Then when we implement that function for real, we don't have to search the entire code base to see where to put it.
Quoted 3 lines
Quoted 1 line
Kinda off-topic though. Feel free to ignore the above comment.
ok I'll add a TODO/emptyfunction for that.
So is using resolve_gitdir not ok when trying to see if a submodule has a gitdir at a particular path?
Signature · 1 line
Brandon Williams
Re: [PATCHv6 4/7] worktree: get worktrees from submodules
Quoted 68 lines · Brandon Williams
Quoted 67 lines · Stefan Beller
Quoted 10 lines · Duy Nguyen
Review static struct worktree *get_main_worktree(void)
Quoted 4 lines · Stefan Beller
worktree = xcalloc(1, sizeof(*worktree)); worktree->path = strbuf_detach(&worktree_path, NULL);(quoted diff) +0
-0@@ -101,7 +101,8 @@ static struct worktree *get_main_worktree(void)All the good stuff is outside context lines again.. Somewhere between here we call
add_head_info()which callsresolve_ref_unsafe(), which always uses data from current repo, not the submodule we want it to look at.Unrelated side question: What would you think of "variable context line configuration" ? e.g. you could configure it to include anything from up that line
that is currently shown after the @@ which is the function signature line.As to the add_head_info/resolve_ref_unsafe what impact does that have? It produces a wrong head info but AFAICT it will never
die(), such that for the purposes of this series (which only wants to know if a submodule uses the worktree feature) it should be fine.It is highly misleading though for others to build upon this. So maybe I'll only add the functionality internally in
worktree.cand document why the values are wrong, and only expose the "intsubmodule_uses_worktrees(const char *path)" ?Quoted 7 lines
worktree.c struct worktree **get_worktrees(unsigned flags) · line 211
Quoted 2 lines
worktree.c +0
-0@@ -209,6 +211,30 @@ struct worktree **get_worktrees(unsigned flags)return list;Right before this line is
mark_current_worktree(), which in turn callsget_git_dir()and not suitable for peeking into another repository the way submodule code does.get_worktree_git_dir()called within that function shares the same problem.It actually works correctly: "No submodule is the current worktree".
Quoted 29 lines
Quoted 10 lines
worktree.c +7
-0} +struct worktree **get_worktrees (unsigned flags) +{ +return get_worktrees_internal (get_git_common_dir (), flags); +} + +struct worktree **get_submodule_worktrees (const char *path,unsigned flags) +{worktree.c struct worktree **get_worktrees(unsigned flags) · line 230
Quoted 10 lines
worktree.c +10
-0+char *submodule_gitdir; +struct strbuf sb =STRBUF_INIT ; +struct worktree **ret; + + submodule_gitdir =git_pathdup_submodule (path,"%s" ,"" ); +if (!submodule_gitdir) +return NULL ; + +/* the env would be set for the superproject */ +get_common_dir_noenv (&sb, submodule_gitdir);Technically we need to read submodule_gitdir/.config and see if we can understand core.repositoryformatversion, or find any unrecognized extensions. But the problem is not specific to this code. And fixing it is no small task. But perhaps we could call a dummy
validate_submodule_gitdir()here? Then when we implement that function for real, we don't have to search the entire code base to see where to put it.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Kinda off-topic though. Feel free to ignore the above comment.
ok I'll add a TODO/emptyfunction for that.
So is using
resolve_gitdirnot ok when trying to see if a submodule has a gitdir at a particular path?
Well it depends on the question that you are trying to answer:
Assume we introduce a new repository format in Git version 3.0. By some means the submodule repository is converted to the new format, but the superproject is not. (e.g. it is auto migrating repositories that have a lot of large blobs/files)
Now for some reason you use the older git 2.X in the superproject. (e.g. the code is on a shared network mount, or git3 has a bug, or ...)
Then the code above may tell that the submodule doesn't use worktrees (as we cannot make any assumptions on the new crazy repository format), but in fact it is, so in this case we technically we would need to:
1) read the config
2) check the repository format version (if larger than we know of, assume the worst or just die?)
As the function in this patch is used for safe guarding we may want to be extra cautious, another function that is using resolve_gitdir may have other assumptions on what is ok even for newer repository formats.
PATCH v6 5/7 worktree: add function to check if worktrees are in use
In reply to Stefan Beller--- worktree.c | 24 ++++++++++++++++++++++++ worktree.h | 7 +++++++ 2 files changed, 31 insertions(+)
worktree.c +24 -0
@@ -406,3 +406,27 @@ const struct worktree *find_shared_symref(const char *symref,return existing; } + +static int uses_worktree_internal (struct worktree **worktrees) +{ +int i; +for (i =0 ; worktrees[i]; i++) + ;/* nothing */ + +free_worktrees (worktrees); +return i >1 ; +} + +int uses_worktrees (void ) +{ +return uses_worktree_internal (get_worktrees (0 )); +} + +int submodule_uses_worktrees (const char *path) +{ +struct worktree **worktrees =get_submodule_worktrees (path,0 ); +if (!worktrees) +return 0 ; + +return uses_worktree_internal (worktrees); +}
worktree.h +7 -0
@@ -33,6 +33,13 @@ extern struct worktree **get_worktrees(unsigned flags);extern struct worktree **get_submodule_worktrees (const char *path,unsigned flags); +/* +* Returns 1 if more than one worktree exists. +* Returns 0 if only the main worktree exists. +*/ +extern int uses_worktrees (void ); +extern int submodule_uses_worktrees (const char *path); +/* * Return git dir of the worktree. Note that the path may be relative. * If wt is NULL, git dir of current worktree is returned.
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
Re: [PATCHv6 5/7] worktree: add function to check if worktrees are in use
Quoted 12 lines · Stefan Beller
Signed-off-by Stefan Beller <[email protected]>--- worktree.c | 24 ++++++++++++++++++++++++ worktree.h | 7 +++++++ 2 files changed, 31 insertions(+)worktree.c +0
-0@@ -406,3 +406,27 @@ const struct worktree *find_shared_symref(const char *symref,
worktree.c const struct worktree *find_shared_symref(const char *symref, · line 416
Quoted 10 lines
worktree.c +8
-0return existing; } + +static int uses_worktree_internal (struct worktree **worktrees) +{ +int i; +for (i =0 ; worktrees[i]; i++) + ;/* nothing */ + +free_worktrees (worktrees);
Ayy.. caller allocates, callee frees. This might become a new maintenance nightmare. Elsewhere I believe we (Junio and me) discussed the possibility of returning the number of worktrees from get_worktrees() too. get_worktrees() would take an "int *", if not NULL, we return the number of worktrees in that pointer.
It's probably a better approach, although I'm afraid it'll add a bit more work on you.
Alternatively, we could add a new flag to get_worktrees() to tell it to return all worktrees if there is a least one linked worktree, or return NULL if there's only main worktree. I'm not sure if this is clever or very stupid.
worktree.c const struct worktree *find_shared_symref(const char *symref, · line 420
Quoted 4 lines
worktree.c +4
-0+return i >1 ; +} + +int uses_worktrees (void )
"has" may be a better verb than "uses". maybe "has_linked_worktrees" since we always have and use the main worktree.
Quoted 33 lines
worktree.c +12
-0+{ +return uses_worktree_internal (get_worktrees (0 )); +} + +int submodule_uses_worktrees (const char *path) +{ +struct worktree **worktrees =get_submodule_worktrees (path,0 ); +if (!worktrees) +return 0 ; + +return uses_worktree_internal (worktrees); +}worktree.h +7
-1@@ -33,6 +33,13 @@ extern struct worktree **get_worktrees(unsigned flags);extern struct worktree **get_submodule_worktrees (const char *path,unsigned flags); +/* +* Returns 1 if more than one worktree exists. +* Returns 0 if only the main worktree exists. +*/ +extern int uses_worktrees (void ); +extern int submodule_uses_worktrees (const char *path); +/* * Return git dir of the worktree. Note that the path may be relative. * If wt is NULL, git dir of current worktree is returned. -- 2.11.0.rc2.30.gc512cbd.dirty
Signature · 1 line
Duy
Re: [PATCHv6 5/7] worktree: add function to check if worktrees are in use
Quoted 4 lines · Duy Nguyen
Alternatively, we could add a new flag to
get_worktrees()to tell it to return all worktrees if there is a least one linked worktree, or return NULL if there's only main worktree. I'm not sure if this is clever or very stupid.
No, this may be better. Add a flag to say "returns linked worktrees _only_". Which means when you're in a "normal" repo, get_worktrees() with this flag returns NULL. When you're in a multiple-worktree repo, it returns all linked worktrees (no main worktree). I think I might have a use for this flag in addition to this uses_worktrees() here. uses_worktrees() look quite simple with that flag
int uses_worktrees(void)
{
struct worktree **worktrees = get_worktrees(WT_LINKED_ONLY);
int retval = worktrees != NULL;
free_worktrees(worktrees);
return retval;
}Signature · 1 line
Duy
Re: [PATCHv6 5/7] worktree: add function to check if worktrees are in use
Quoted 13 lines · Duy Nguyen
Quoted 4 lines · Duy Nguyen
Alternatively, we could add a new flag to
get_worktrees()to tell it to return all worktrees if there is a least one linked worktree, or return NULL if there's only main worktree. I'm not sure if this is clever or very stupid.No, this may be better. Add a flag to say "returns linked worktrees _only_". Which means when you're in a "normal" repo,
get_worktrees()with this flag returns NULL. When you're in a multiple-worktree repo, it returns all linked worktrees (no main worktree). I think I might have a use for this flag in addition to thisuses_worktrees()here.uses_worktrees()look quite simple with that flag
Quoted 4 lines
int
uses_worktrees(void){ struct worktree **worktrees = get_worktrees(WT_LINKED_ONLY); int retval = worktrees != NULL;
I am interested in the submodule case however, where we already return NULL e.g. when the submodule git dir cannot be found. Actually that would work out fine
as well:
/* NOTE on accuracy of result, hence not exposed. */
static worktree **submodule_get_worktrees(const char *path, unsigned flags) ..
int submodule_uses_worktrees(const char *path)
{
struct worktree **worktrees = submodule_get_worktrees(path,
WT_LINKED_ONLY);
int retval = worktrees != NULL;
free_worktrees(worktrees);
return retval;
}Thanks for that inspiration!
PATCH v6 6/7 move connect_work_tree_and_git_dir to dir.h
In reply to Stefan BellerThat function was primarily used by submodule code, but the function itself is not inherently about submodules. In the next patch we'll introduce relocate_git_dir, which can be used by worktrees as well, so find a neutral middle ground in dir.h.
--- dir.c | 26 ++++++++++++++++++++++++++ dir.h | 1 + submodule.c | 26 -------------------------- submodule.h | 1 - 4 files changed, 27 insertions(+), 27 deletions(-)
dir.c +26 -0
@@ -2748,3 +2748,29 @@ void untracked_cache_add_to_index(struct index_state *istate, {untracked_cache_invalidate_path (istate, path); } + +/* Update gitfile and core.worktree setting to connect work tree and git dir */ +void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir) +{ +struct strbuf file_name =STRBUF_INIT ; +struct strbuf rel_path =STRBUF_INIT ; +char *real_git_dir =xstrdup (real_path (git_dir)); +char *real_work_tree =xstrdup (real_path (work_tree)); + +/* Update gitfile */ +strbuf_addf (&file_name,"%s/.git" , work_tree); +write_file (file_name.buf,"gitdir: %s" , +relative_path (real_git_dir, real_work_tree, &rel_path)); + +/* Update core.worktree setting */ +strbuf_reset (&file_name); +strbuf_addf (&file_name,"%s/config" , real_git_dir); +git_config_set_in_file (file_name.buf,"core.worktree" , +relative_path (real_work_tree, real_git_dir, + &rel_path)); + +strbuf_release (&file_name); +strbuf_release (&rel_path); +free (real_work_tree); +free (real_git_dir); +}
dir.h +1 -0
@@ -335,4 +335,5 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned longvoid write_untracked_extension (struct strbuf *out,struct untracked_cache *untracked);void add_untracked_cache (struct index_state *istate);void remove_untracked_cache (struct index_state *istate); +extern void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir);#endif
submodule.c +0 -26
@@ -1222,32 +1222,6 @@ int merge_submodule(unsigned char result[20], const char *path,return 0 ; } -/* Update gitfile and core.worktree setting to connect work tree and git dir */ -void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir) -{ -struct strbuf file_name =STRBUF_INIT ; -struct strbuf rel_path =STRBUF_INIT ; -char *real_git_dir =xstrdup (real_path (git_dir)); -char *real_work_tree =xstrdup (real_path (work_tree)); - -/* Update gitfile */ -strbuf_addf (&file_name,"%s/.git" , work_tree); -write_file (file_name.buf,"gitdir: %s" , -relative_path (real_git_dir, real_work_tree, &rel_path)); - -/* Update core.worktree setting */ -strbuf_reset (&file_name); -strbuf_addf (&file_name,"%s/config" , real_git_dir); -git_config_set_in_file (file_name.buf,"core.worktree" , -relative_path (real_work_tree, real_git_dir, - &rel_path)); - -strbuf_release (&file_name); -strbuf_release (&rel_path); -free (real_work_tree); -free (real_git_dir); -} -int parallel_submodules (void ) {return parallel_jobs;
submodule.h +0 -1
@@ -65,7 +65,6 @@ int merge_submodule(unsigned char result[20], const char *path, const unsigned cint find_unpushed_submodules (unsigned char new_sha1[20 ],const char *remotes_name,struct string_list *needs_pushing);int push_unpushed_submodules (unsigned char new_sha1[20 ],const char *remotes_name); -void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir);int parallel_submodules (void );/*
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
PATCH v6 7/7 submodule: add absorb-git-dir function
In reply to Stefan BellerWhen a submodule has its git dir inside the working dir, the submodule support for checkout that we plan to add in a later patch will fail.
Add functionality to migrate the git directory to be absorbed into the superprojects git directory.
The newly added code in this patch is structured such that other areas of Git can also make use of it. The code in the submodule--helper is a mere wrapper and option parser for the function absorb_git_dir_into_superproject, that takes care of embedding the submodules git directory into the superprojects git dir. That function makes use of the more abstract function for this use case relocate_gitdir, which can be used by e.g. the worktree code eventually to move around a git directory.
--- Documentation/git-submodule.txt | 15 ++++++ builtin/submodule--helper.c | 38 ++++++++++++++ dir.c | 12 +++++ dir.h | 3 ++ git-submodule.sh | 7 ++- submodule.c | 103 +++++++++++++++++++++++++++++++++++++ submodule.h | 4 ++ t/t7412-submodule-absorbgitdirs.sh | 101 ++++++++++++++++++++++++++++++++++++ 8 files changed, 282 insertions(+), 1 deletion(-) create mode 100755 t/t7412-submodule-absorbgitdirs.sh
Documentation/git-submodule.txt +15 -0
@@ -22,6 +22,7 @@ SYNOPSIS [commit] [--] [<path>...] 'git submodule' [--quiet] foreach [--recursive] <command> 'git submodule' [--quiet] sync [--recursive] [--] [<path>...] +'git submodule' [--quiet] absorbgitdirs [--] [<path>...] DESCRIPTION
@@ -245,6 +246,20 @@ sync:: If `--recursive` is specified, this command will recurse into the registered submodules, and sync any nested submodules within. +absorbgitdirs:: + If a git directory of a submodule is inside the submodule, + move the git directory of the submodule into its superprojects + `$GIT_DIR/modules` path and then connect the git directory and + its working directory by setting the `core.worktree` and adding + a .git file pointing to the git directory embedded in the + superprojects git directory. ++ +A repository that was cloned independently and later added as a submodule or +old setups have the submodules git directory inside the submodule instead of +embedded into the superprojects git directory. ++ +This command is recursive by default. + OPTIONS ------- -q::
builtin/submodule--helper.c +38 -0
@@ -1076,6 +1076,43 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,return 0 ; } +static int absorb_git_dirs (int argc,const char **argv,const char *prefix) +{ +int i; +struct pathspec pathspec; +struct module_list list =MODULE_LIST_INIT ; +unsigned flags =ABSORB_GITDIR_RECURSE_SUBMODULES ; + +struct option embed_gitdir_options[] = { +OPT_STRING (0 ,"prefix" , &prefix, +N_ ("path" ), +N_ ("path into the working tree" )), +OPT_BIT (0 ,"--recursive" , &flags,N_ ("recurse into submodules" ), +ABSORB_GITDIR_RECURSE_SUBMODULES ), +OPT_END () + }; + +const char *const git_submodule_helper_usage[] = { +N_ ("git submodule--helper embed-git-dir [<path>...]" ), +NULL + }; + + argc =parse_options (argc, argv, prefix, embed_gitdir_options, + git_submodule_helper_usage,0 ); + +gitmodules_config (); +git_config (submodule_config,NULL ); + +if (module_list_compute (argc, argv, prefix, &pathspec, &list) <0 ) +return 1 ; + +for (i =0 ; i < list.nr; i++) +absorb_git_dir_into_superproject (prefix, + list.entries[i]->name, flags); + +return 0 ; +} +#define SUPPORT_SUPER_PREFIX (1<<0)struct cmd_struct {
@@ -1094,6 +1131,7 @@ static struct cmd_struct commands[] = { {"resolve-relative-url-test", resolve_relative_url_test, 0}, {"init", module_init, 0}, {"remote-branch", resolve_remote_submodule_branch, 0}, + {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX}, };int cmd_submodule__helper (int argc,const char **argv,const char *prefix)
dir.c +12 -0
@@ -2774,3 +2774,15 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)free (real_work_tree);free (real_git_dir); } + +/* +* Migrate the git directory of the given path from old_git_dir to new_git_dir. +*/ +void relocate_gitdir (const char *path,const char *old_git_dir,const char *new_git_dir) +{ +if (rename (old_git_dir, new_git_dir) <0 ) +die_errno (_ ("could not migrate git directory from '%s' to '%s'" ), + old_git_dir, new_git_dir); + +connect_work_tree_and_git_dir (path, new_git_dir); +}
dir.h +3 -0
@@ -336,4 +336,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untravoid add_untracked_cache (struct index_state *istate);void remove_untracked_cache (struct index_state *istate);extern void connect_work_tree_and_git_dir (const char *work_tree,const char *git_dir); +extern void relocate_gitdir (const char *path, +const char *old_git_dir, +const char *new_git_dir);#endif
git-submodule.sh +6 -1
@@ -1131,6 +1131,11 @@ cmd_sync() done } +cmd_absorbgitdirs() +{ + git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@" +} + # This loop parses the command line arguments to find the # subcommand name to dispatch. Parsing of the subcommand specific # options are primarily done by the subcommand implementations.
@@ -1140,7 +1145,7 @@ cmd_sync() while test $# != 0 && test -z "$command" do case "$1" in - add | foreach | init | deinit | update | status | summary | sync) + add | foreach | init | deinit | update | status | summary | sync | absorbgitdirs) command=$1 ;; -q|--quiet)
submodule.c +103 -0
112 lines not on this page · raw message
submodule.h +4 -0
@@ -74,4 +74,8 @@ int parallel_submodules(void);*/ void prepare_submodule_repo_env (struct argv_array *out); +#define ABSORB_GITDIR_RECURSE_SUBMODULES (1<<0) +extern void absorb_git_dir_into_superproject (const char *prefix, +const char *path, +unsigned flags);#endif
t/t7412-submodule-absorbgitdirs.sh new file +101 -0
101 lines not on this page · raw message
Signature · 1 line
2.11.0.rc2.30.gc512cbd.dirty
Re: [PATCHv6 7/7] submodule: add absorb-git-dir function
Quoted 10 lines · Stefan Beller
dir.c +2
-0@@ -2774,3 +2774,15 @@ void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir)free (real_work_tree);free (real_git_dir); } + +/*
dir.c void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir) · line 2788
Quoted 10 lines
dir.c +10
-0+* Migrate the git directory of the given path from old_git_dir to new_git_dir. +*/ +void relocate_gitdir (const char *path,const char *old_git_dir,const char *new_git_dir) +{ +if (rename (old_git_dir, new_git_dir) <0 ) +die_errno (_ ("could not migrate git directory from '%s' to '%s'" ), + old_git_dir, new_git_dir); + +connect_work_tree_and_git_dir (path, new_git_dir); +}
Thank you!
Signature · 1 line
Duy