Skip to content

Commit

Permalink
Merge branch 'sb/submodule-move-nested'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed May 8, 2018
2 parents 92034a9 + da62f78 commit 0c7ecb7
Show file tree
Hide file tree
Showing 15 changed files with 140 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Documentation/technical/api-submodule-config.txt
Expand Up @@ -38,7 +38,7 @@ Data Structures
Functions
---------

`void submodule_free()`::
`void submodule_free(struct repository *r)`::

Use these to free the internally cached values.

Expand Down
14 changes: 6 additions & 8 deletions builtin/grep.c
Expand Up @@ -602,8 +602,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
}

static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
struct object *obj, const char *name, const char *path,
struct repository *repo)
struct object *obj, const char *name, const char *path)
{
if (obj->type == OBJ_BLOB)
return grep_oid(opt, &obj->oid, name, 0, path);
Expand All @@ -630,7 +629,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
}
init_tree_desc(&tree, data, size);
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
obj->type == OBJ_COMMIT, repo);
obj->type == OBJ_COMMIT, the_repository);
strbuf_release(&base);
free(data);
return hit;
Expand All @@ -639,7 +638,6 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
}

static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
struct repository *repo,
const struct object_array *list)
{
unsigned int i;
Expand All @@ -652,11 +650,11 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,

/* load the gitmodules file for this rev */
if (recurse_submodules) {
submodule_free();
submodule_free(the_repository);
gitmodules_config_oid(&real_obj->oid);
}
if (grep_object(opt, pathspec, real_obj, list->objects[i].name, list->objects[i].path,
repo)) {
if (grep_object(opt, pathspec, real_obj, list->objects[i].name,
list->objects[i].path)) {
hit = 1;
if (opt->status_only)
break;
Expand Down Expand Up @@ -1108,7 +1106,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (cached)
die(_("both --cached and trees are given."));

hit = grep_objects(&opt, &pathspec, the_repository, &list);
hit = grep_objects(&opt, &pathspec, &list);
}

if (num_threads)
Expand Down
6 changes: 4 additions & 2 deletions builtin/mv.c
Expand Up @@ -276,10 +276,12 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
die_errno(_("renaming '%s' failed"), src);
}
if (submodule_gitfile[i]) {
if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
connect_work_tree_and_git_dir(dst, submodule_gitfile[i]);
if (!update_path_in_gitmodules(src, dst))
gitmodules_modified = 1;
if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
connect_work_tree_and_git_dir(dst,
submodule_gitfile[i],
1);
}

if (mode == WORKING_DIRECTORY)
Expand Down
17 changes: 8 additions & 9 deletions builtin/submodule--helper.c
Expand Up @@ -455,7 +455,7 @@ static void init_submodule(const char *path, const char *prefix,

displaypath = get_submodule_displaypath(path, prefix);

sub = submodule_from_path(&null_oid, path);
sub = submodule_from_path(the_repository, &null_oid, path);

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

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

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

sub = submodule_from_path(&null_oid, argv[1]);
sub = submodule_from_path(the_repository, &null_oid, argv[1]);

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

sub = submodule_from_path(&null_oid, path);
sub = submodule_from_path(the_repository, &null_oid, path);

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

sub = submodule_from_path(&null_oid, path);
sub = submodule_from_path(the_repository, &null_oid, path);

if (!sub || !sub->name)
goto cleanup;
Expand Down Expand Up @@ -1264,8 +1264,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
strbuf_reset(&sb);
}

/* Connect module worktree and git dir */
connect_work_tree_and_git_dir(path, sm_gitdir);
connect_work_tree_and_git_dir(path, sm_gitdir, 0);

p = git_pathdup_submodule(path, "config");
if (!p)
Expand Down Expand Up @@ -1372,7 +1371,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}

sub = submodule_from_path(&null_oid, ce->name);
sub = submodule_from_path(the_repository, &null_oid, ce->name);

if (suc->recursive_prefix)
displaypath = relative_path(suc->recursive_prefix,
Expand Down Expand Up @@ -1655,7 +1654,7 @@ static const char *remote_submodule_branch(const char *path)
const char *branch = NULL;
char *key;

sub = submodule_from_path(&null_oid, path);
sub = submodule_from_path(the_repository, &null_oid, path);
if (!sub)
return NULL;

Expand Down
60 changes: 57 additions & 3 deletions dir.c
Expand Up @@ -19,6 +19,7 @@
#include "varint.h"
#include "ewah/ewok.h"
#include "fsmonitor.h"
#include "submodule-config.h"

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

/* 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_)
static void connect_wt_gitdir_in_nested(const char *sub_worktree,
const char *sub_gitdir)
{
int i;
struct repository subrepo;
struct strbuf sub_wt = STRBUF_INIT;
struct strbuf sub_gd = STRBUF_INIT;

const struct submodule *sub;

/* If the submodule has no working tree, we can ignore it. */
if (repo_init(&subrepo, sub_gitdir, sub_worktree))
return;

if (repo_read_index(&subrepo) < 0)
die("index file corrupt in repo %s", subrepo.gitdir);

for (i = 0; i < subrepo.index->cache_nr; i++) {
const struct cache_entry *ce = subrepo.index->cache[i];

if (!S_ISGITLINK(ce->ce_mode))
continue;

while (i + 1 < subrepo.index->cache_nr &&
!strcmp(ce->name, subrepo.index->cache[i + 1]->name))
/*
* Skip entries with the same name in different stages
* to make sure an entry is returned only once.
*/
i++;

sub = submodule_from_path(&subrepo, &null_oid, ce->name);
if (!sub || !is_submodule_active(&subrepo, ce->name))
/* .gitmodules broken or inactive sub */
continue;

strbuf_reset(&sub_wt);
strbuf_reset(&sub_gd);
strbuf_addf(&sub_wt, "%s/%s", sub_worktree, sub->path);
strbuf_addf(&sub_gd, "%s/modules/%s", sub_gitdir, sub->name);

connect_work_tree_and_git_dir(sub_wt.buf, sub_gd.buf, 1);
}
strbuf_release(&sub_wt);
strbuf_release(&sub_gd);
repo_clear(&subrepo);
}

void connect_work_tree_and_git_dir(const char *work_tree_,
const char *git_dir_,
int recurse_into_nested)
{
struct strbuf gitfile_sb = STRBUF_INIT;
struct strbuf cfg_sb = STRBUF_INIT;
Expand Down Expand Up @@ -3041,6 +3091,10 @@ void connect_work_tree_and_git_dir(const char *work_tree_, const char *git_dir_)
strbuf_release(&gitfile_sb);
strbuf_release(&cfg_sb);
strbuf_release(&rel_path);

if (recurse_into_nested)
connect_wt_gitdir_in_nested(work_tree, git_dir);

free(work_tree);
free(git_dir);
}
Expand All @@ -3054,5 +3108,5 @@ void relocate_gitdir(const char *path, const char *old_git_dir, const char *new_
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);
connect_work_tree_and_git_dir(path, new_git_dir, 0);
}
12 changes: 11 additions & 1 deletion dir.h
Expand Up @@ -359,7 +359,17 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long
void 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);

/*
* Connect a worktree to a git directory by creating (or overwriting) a
* '.git' file containing the location of the git directory. In the git
* directory set the core.worktree setting to indicate where the worktree is.
* When `recurse_into_nested` is set, recurse into any nested submodules,
* connecting them as well.
*/
extern void connect_work_tree_and_git_dir(const char *work_tree,
const char *git_dir,
int recurse_into_nested);
extern void relocate_gitdir(const char *path,
const char *old_git_dir,
const char *new_git_dir);
Expand Down
8 changes: 4 additions & 4 deletions repository.c
Expand Up @@ -135,9 +135,9 @@ static int read_and_verify_repository_format(struct repository_format *format,
* Initialize 'repo' based on the provided 'gitdir'.
* Return 0 upon success and a non-zero value upon failure.
*/
static int repo_init(struct repository *repo,
const char *gitdir,
const char *worktree)
int repo_init(struct repository *repo,
const char *gitdir,
const char *worktree)
{
struct repository_format format;
memset(repo, 0, sizeof(*repo));
Expand Down Expand Up @@ -176,7 +176,7 @@ int repo_submodule_init(struct repository *submodule,
struct strbuf worktree = STRBUF_INIT;
int ret = 0;

sub = submodule_from_cache(superproject, &null_oid, path);
sub = submodule_from_path(superproject, &null_oid, path);
if (!sub) {
ret = -1;
goto out;
Expand Down
3 changes: 3 additions & 0 deletions repository.h
Expand Up @@ -97,6 +97,9 @@ extern void repo_set_gitdir(struct repository *repo,
extern void repo_set_worktree(struct repository *repo, const char *path);
extern void repo_set_hash_algo(struct repository *repo, int algo);
extern void initialize_the_repository(void);
extern int repo_init(struct repository *r,
const char *gitdir,
const char *worktree);
extern int repo_submodule_init(struct repository *submodule,
struct repository *superproject,
const char *path);
Expand Down
29 changes: 11 additions & 18 deletions submodule-config.c
Expand Up @@ -619,31 +619,24 @@ static void gitmodules_read_check(struct repository *repo)
repo_read_gitmodules(repo);
}

const struct submodule *submodule_from_name(const struct object_id *treeish_name,
const struct submodule *submodule_from_name(struct repository *r,
const struct object_id *treeish_name,
const char *name)
{
gitmodules_read_check(the_repository);
return config_from(the_repository->submodule_cache, treeish_name, name, lookup_name);
gitmodules_read_check(r);
return config_from(r->submodule_cache, treeish_name, name, lookup_name);
}

const struct submodule *submodule_from_path(const struct object_id *treeish_name,
const struct submodule *submodule_from_path(struct repository *r,
const struct object_id *treeish_name,
const char *path)
{
gitmodules_read_check(the_repository);
return config_from(the_repository->submodule_cache, treeish_name, path, lookup_path);
gitmodules_read_check(r);
return config_from(r->submodule_cache, treeish_name, path, lookup_path);
}

const struct submodule *submodule_from_cache(struct repository *repo,
const struct object_id *treeish_name,
const char *key)
void submodule_free(struct repository *r)
{
gitmodules_read_check(repo);
return config_from(repo->submodule_cache, treeish_name,
key, lookup_path);
}

void submodule_free(void)
{
if (the_repository->submodule_cache)
submodule_cache_clear(the_repository->submodule_cache);
if (r->submodule_cache)
submodule_cache_clear(r->submodule_cache);
}
15 changes: 7 additions & 8 deletions submodule-config.h
Expand Up @@ -39,13 +39,12 @@ extern int parse_update_recurse_submodules_arg(const char *opt, const char *arg)
extern int parse_push_recurse_submodules_arg(const char *opt, const char *arg);
extern void repo_read_gitmodules(struct repository *repo);
extern void gitmodules_config_oid(const struct object_id *commit_oid);
extern const struct submodule *submodule_from_name(
const struct object_id *commit_or_tree, const char *name);
extern const struct submodule *submodule_from_path(
const struct object_id *commit_or_tree, const char *path);
extern const struct submodule *submodule_from_cache(struct repository *repo,
const struct object_id *treeish_name,
const char *key);
extern void submodule_free(void);
const struct submodule *submodule_from_name(struct repository *r,
const struct object_id *commit_or_tree,
const char *name);
const struct submodule *submodule_from_path(struct repository *r,
const struct object_id *commit_or_tree,
const char *path);
void submodule_free(struct repository *r);

#endif /* SUBMODULE_CONFIG_H */

0 comments on commit 0c7ecb7

Please sign in to comment.