Skip to content

Commit 0c7ecb7

Browse files
committed
Merge branch 'sb/submodule-move-nested'
Moving a submodule that itself has submodule in it with "git mv" forgot to make necessary adjustment to the nested sub-submodules; now the codepath learned to recurse into the submodules. * sb/submodule-move-nested: submodule: fixup nested submodules after moving the submodule submodule-config: remove submodule_from_cache submodule-config: add repository argument to submodule_from_{name, path} submodule-config: allow submodule_free to handle arbitrary repositories grep: remove "repo" arg from non-supporting funcs submodule.h: drop declaration of connect_work_tree_and_git_dir
2 parents 92034a9 + da62f78 commit 0c7ecb7

File tree

15 files changed

+140
-79
lines changed

15 files changed

+140
-79
lines changed

Documentation/technical/api-submodule-config.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Data Structures
3838
Functions
3939
---------
4040

41-
`void submodule_free()`::
41+
`void submodule_free(struct repository *r)`::
4242

4343
Use these to free the internally cached values.
4444

builtin/grep.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
602602
}
603603

604604
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
605-
struct object *obj, const char *name, const char *path,
606-
struct repository *repo)
605+
struct object *obj, const char *name, const char *path)
607606
{
608607
if (obj->type == OBJ_BLOB)
609608
return grep_oid(opt, &obj->oid, name, 0, path);
@@ -630,7 +629,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
630629
}
631630
init_tree_desc(&tree, data, size);
632631
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
633-
obj->type == OBJ_COMMIT, repo);
632+
obj->type == OBJ_COMMIT, the_repository);
634633
strbuf_release(&base);
635634
free(data);
636635
return hit;
@@ -639,7 +638,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
639638
}
640639

641640
static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
642-
struct repository *repo,
643641
const struct object_array *list)
644642
{
645643
unsigned int i;
@@ -652,11 +650,11 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
652650

653651
/* load the gitmodules file for this rev */
654652
if (recurse_submodules) {
655-
submodule_free();
653+
submodule_free(the_repository);
656654
gitmodules_config_oid(&real_obj->oid);
657655
}
658-
if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
659-
repo)) {
656+
if (grep_object(opt, pathspec, real_obj, list->objects[i].name,
657+
list->objects[i].path)) {
660658
hit = 1;
661659
if (opt->status_only)
662660
break;
@@ -1108,7 +1106,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11081106
if (cached)
11091107
die(_("both --cached and trees are given."));
11101108

1111-
hit = grep_objects(&opt, &pathspec, the_repository, &list);
1109+
hit = grep_objects(&opt, &pathspec, &list);
11121110
}
11131111

11141112
if (num_threads)

builtin/mv.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
276276
die_errno(_("renaming '%s' failed"), src);
277277
}
278278
if (submodule_gitfile[i]) {
279-
if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
280-
connect_work_tree_and_git_dir(dst, submodule_gitfile[i]);
281279
if (!update_path_in_gitmodules(src, dst))
282280
gitmodules_modified = 1;
281+
if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
282+
connect_work_tree_and_git_dir(dst,
283+
submodule_gitfile[i],
284+
1);
283285
}
284286

285287
if (mode == WORKING_DIRECTORY)

builtin/submodule--helper.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ static void init_submodule(const char *path, const char *prefix,
455455

456456
displaypath = get_submodule_displaypath(path, prefix);
457457

458-
sub = submodule_from_path(&null_oid, path);
458+
sub = submodule_from_path(the_repository, &null_oid, path);
459459

460460
if (!sub)
461461
die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -622,7 +622,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
622622
struct rev_info rev;
623623
int diff_files_result;
624624

625-
if (!submodule_from_path(&null_oid, path))
625+
if (!submodule_from_path(the_repository, &null_oid, path))
626626
die(_("no submodule mapping found in .gitmodules for path '%s'"),
627627
path);
628628

@@ -746,7 +746,7 @@ static int module_name(int argc, const char **argv, const char *prefix)
746746
if (argc != 2)
747747
usage(_("git submodule--helper name <path>"));
748748

749-
sub = submodule_from_path(&null_oid, argv[1]);
749+
sub = submodule_from_path(the_repository, &null_oid, argv[1]);
750750

751751
if (!sub)
752752
die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -777,7 +777,7 @@ static void sync_submodule(const char *path, const char *prefix,
777777
if (!is_submodule_active(the_repository, path))
778778
return;
779779

780-
sub = submodule_from_path(&null_oid, path);
780+
sub = submodule_from_path(the_repository, &null_oid, path);
781781

782782
if (sub && sub->url) {
783783
if (starts_with_dot_dot_slash(sub->url) ||
@@ -930,7 +930,7 @@ static void deinit_submodule(const char *path, const char *prefix,
930930
struct strbuf sb_config = STRBUF_INIT;
931931
char *sub_git_dir = xstrfmt("%s/.git", path);
932932

933-
sub = submodule_from_path(&null_oid, path);
933+
sub = submodule_from_path(the_repository, &null_oid, path);
934934

935935
if (!sub || !sub->name)
936936
goto cleanup;
@@ -1264,8 +1264,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
12641264
strbuf_reset(&sb);
12651265
}
12661266

1267-
/* Connect module worktree and git dir */
1268-
connect_work_tree_and_git_dir(path, sm_gitdir);
1267+
connect_work_tree_and_git_dir(path, sm_gitdir, 0);
12691268

12701269
p = git_pathdup_submodule(path, "config");
12711270
if (!p)
@@ -1372,7 +1371,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
13721371
goto cleanup;
13731372
}
13741373

1375-
sub = submodule_from_path(&null_oid, ce->name);
1374+
sub = submodule_from_path(the_repository, &null_oid, ce->name);
13761375

13771376
if (suc->recursive_prefix)
13781377
displaypath = relative_path(suc->recursive_prefix,
@@ -1655,7 +1654,7 @@ static const char *remote_submodule_branch(const char *path)
16551654
const char *branch = NULL;
16561655
char *key;
16571656

1658-
sub = submodule_from_path(&null_oid, path);
1657+
sub = submodule_from_path(the_repository, &null_oid, path);
16591658
if (!sub)
16601659
return NULL;
16611660

dir.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "varint.h"
2020
#include "ewah/ewok.h"
2121
#include "fsmonitor.h"
22+
#include "submodule-config.h"
2223

2324
/*
2425
* Tells read_directory_recursive how a file or directory should be treated.
@@ -3010,8 +3011,57 @@ void untracked_cache_add_to_index(struct index_state *istate,
30103011
untracked_cache_invalidate_path(istate, path, 1);
30113012
}
30123013

3013-
/* Update gitfile and core.worktree setting to connect work tree and git dir */
3014-
void connect_work_tree_and_git_dir(const char *work_tree_, const char *git_dir_)
3014+
static void connect_wt_gitdir_in_nested(const char *sub_worktree,
3015+
const char *sub_gitdir)
3016+
{
3017+
int i;
3018+
struct repository subrepo;
3019+
struct strbuf sub_wt = STRBUF_INIT;
3020+
struct strbuf sub_gd = STRBUF_INIT;
3021+
3022+
const struct submodule *sub;
3023+
3024+
/* If the submodule has no working tree, we can ignore it. */
3025+
if (repo_init(&subrepo, sub_gitdir, sub_worktree))
3026+
return;
3027+
3028+
if (repo_read_index(&subrepo) < 0)
3029+
die("index file corrupt in repo %s", subrepo.gitdir);
3030+
3031+
for (i = 0; i < subrepo.index->cache_nr; i++) {
3032+
const struct cache_entry *ce = subrepo.index->cache[i];
3033+
3034+
if (!S_ISGITLINK(ce->ce_mode))
3035+
continue;
3036+
3037+
while (i + 1 < subrepo.index->cache_nr &&
3038+
!strcmp(ce->name, subrepo.index->cache[i + 1]->name))
3039+
/*
3040+
* Skip entries with the same name in different stages
3041+
* to make sure an entry is returned only once.
3042+
*/
3043+
i++;
3044+
3045+
sub = submodule_from_path(&subrepo, &null_oid, ce->name);
3046+
if (!sub || !is_submodule_active(&subrepo, ce->name))
3047+
/* .gitmodules broken or inactive sub */
3048+
continue;
3049+
3050+
strbuf_reset(&sub_wt);
3051+
strbuf_reset(&sub_gd);
3052+
strbuf_addf(&sub_wt, "%s/%s", sub_worktree, sub->path);
3053+
strbuf_addf(&sub_gd, "%s/modules/%s", sub_gitdir, sub->name);
3054+
3055+
connect_work_tree_and_git_dir(sub_wt.buf, sub_gd.buf, 1);
3056+
}
3057+
strbuf_release(&sub_wt);
3058+
strbuf_release(&sub_gd);
3059+
repo_clear(&subrepo);
3060+
}
3061+
3062+
void connect_work_tree_and_git_dir(const char *work_tree_,
3063+
const char *git_dir_,
3064+
int recurse_into_nested)
30153065
{
30163066
struct strbuf gitfile_sb = STRBUF_INIT;
30173067
struct strbuf cfg_sb = STRBUF_INIT;
@@ -3041,6 +3091,10 @@ void connect_work_tree_and_git_dir(const char *work_tree_, const char *git_dir_)
30413091
strbuf_release(&gitfile_sb);
30423092
strbuf_release(&cfg_sb);
30433093
strbuf_release(&rel_path);
3094+
3095+
if (recurse_into_nested)
3096+
connect_wt_gitdir_in_nested(work_tree, git_dir);
3097+
30443098
free(work_tree);
30453099
free(git_dir);
30463100
}
@@ -3054,5 +3108,5 @@ void relocate_gitdir(const char *path, const char *old_git_dir, const char *new_
30543108
die_errno(_("could not migrate git directory from '%s' to '%s'"),
30553109
old_git_dir, new_git_dir);
30563110

3057-
connect_work_tree_and_git_dir(path, new_git_dir);
3111+
connect_work_tree_and_git_dir(path, new_git_dir, 0);
30583112
}

dir.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,17 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
359359
void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
360360
void add_untracked_cache(struct index_state *istate);
361361
void remove_untracked_cache(struct index_state *istate);
362-
extern void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
362+
363+
/*
364+
* Connect a worktree to a git directory by creating (or overwriting) a
365+
* '.git' file containing the location of the git directory. In the git
366+
* directory set the core.worktree setting to indicate where the worktree is.
367+
* When `recurse_into_nested` is set, recurse into any nested submodules,
368+
* connecting them as well.
369+
*/
370+
extern void connect_work_tree_and_git_dir(const char *work_tree,
371+
const char *git_dir,
372+
int recurse_into_nested);
363373
extern void relocate_gitdir(const char *path,
364374
const char *old_git_dir,
365375
const char *new_git_dir);

repository.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ static int read_and_verify_repository_format(struct repository_format *format,
135135
* Initialize 'repo' based on the provided 'gitdir'.
136136
* Return 0 upon success and a non-zero value upon failure.
137137
*/
138-
static int repo_init(struct repository *repo,
139-
const char *gitdir,
140-
const char *worktree)
138+
int repo_init(struct repository *repo,
139+
const char *gitdir,
140+
const char *worktree)
141141
{
142142
struct repository_format format;
143143
memset(repo, 0, sizeof(*repo));
@@ -176,7 +176,7 @@ int repo_submodule_init(struct repository *submodule,
176176
struct strbuf worktree = STRBUF_INIT;
177177
int ret = 0;
178178

179-
sub = submodule_from_cache(superproject, &null_oid, path);
179+
sub = submodule_from_path(superproject, &null_oid, path);
180180
if (!sub) {
181181
ret = -1;
182182
goto out;

repository.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ extern void repo_set_gitdir(struct repository *repo,
9797
extern void repo_set_worktree(struct repository *repo, const char *path);
9898
extern void repo_set_hash_algo(struct repository *repo, int algo);
9999
extern void initialize_the_repository(void);
100+
extern int repo_init(struct repository *r,
101+
const char *gitdir,
102+
const char *worktree);
100103
extern int repo_submodule_init(struct repository *submodule,
101104
struct repository *superproject,
102105
const char *path);

submodule-config.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -619,31 +619,24 @@ static void gitmodules_read_check(struct repository *repo)
619619
repo_read_gitmodules(repo);
620620
}
621621

622-
const struct submodule *submodule_from_name(const struct object_id *treeish_name,
622+
const struct submodule *submodule_from_name(struct repository *r,
623+
const struct object_id *treeish_name,
623624
const char *name)
624625
{
625-
gitmodules_read_check(the_repository);
626-
return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
626+
gitmodules_read_check(r);
627+
return config_from(r->submodule_cache, treeish_name, name, lookup_name);
627628
}
628629

629-
const struct submodule *submodule_from_path(const struct object_id *treeish_name,
630+
const struct submodule *submodule_from_path(struct repository *r,
631+
const struct object_id *treeish_name,
630632
const char *path)
631633
{
632-
gitmodules_read_check(the_repository);
633-
return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
634+
gitmodules_read_check(r);
635+
return config_from(r->submodule_cache, treeish_name, path, lookup_path);
634636
}
635637

636-
const struct submodule *submodule_from_cache(struct repository *repo,
637-
const struct object_id *treeish_name,
638-
const char *key)
638+
void submodule_free(struct repository *r)
639639
{
640-
gitmodules_read_check(repo);
641-
return config_from(repo->submodule_cache, treeish_name,
642-
key, lookup_path);
643-
}
644-
645-
void submodule_free(void)
646-
{
647-
if (the_repository->submodule_cache)
648-
submodule_cache_clear(the_repository->submodule_cache);
640+
if (r->submodule_cache)
641+
submodule_cache_clear(r->submodule_cache);
649642
}

submodule-config.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,12 @@ extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
3939
extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
4040
extern void repo_read_gitmodules(struct repository *repo);
4141
extern void gitmodules_config_oid(const struct object_id *commit_oid);
42-
extern const struct submodule *submodule_from_name(
43-
const struct object_id *commit_or_tree, const char *name);
44-
extern const struct submodule *submodule_from_path(
45-
const struct object_id *commit_or_tree, const char *path);
46-
extern const struct submodule *submodule_from_cache(struct repository *repo,
47-
const struct object_id *treeish_name,
48-
const char *key);
49-
extern void submodule_free(void);
42+
const struct submodule *submodule_from_name(struct repository *r,
43+
const struct object_id *commit_or_tree,
44+
const char *name);
45+
const struct submodule *submodule_from_path(struct repository *r,
46+
const struct object_id *commit_or_tree,
47+
const char *path);
48+
void submodule_free(struct repository *r);
5049

5150
#endif /* SUBMODULE_CONFIG_H */

0 commit comments

Comments
 (0)