Here's one more attempt where I changed prepare_submodule_repo_env() to take the submodule git dir as an argument. Sorry for including this long code diff inline. If there's a better way to have this discussion with code please let me know.
Thanks, Uma diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 9d79f19..0741f6c 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -465,7 +465,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url argv_array_push(&cp.args, path); cp.git_cmd = 1; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, gitdir); cp.no_stdin = 1; return run_command(&cp); diff --git a/submodule.c b/submodule.c index 5a62aa2..3d9174a 100644 --- a/submodule.c +++ b/submodule.c @@ -522,11 +522,31 @@ static int has_remote(const char *refname, const struct object_id *oid, return 1; } +static const char *submodule_git_dir = NULL; +const char *get_submodule_git_dir(const char *path, struct strbuf *bufptr) +{ + strbuf_addf(bufptr, "%s/.git", path); + submodule_git_dir = read_gitfile(bufptr->buf); + if (!submodule_git_dir) + submodule_git_dir = bufptr->buf; + if (!is_directory(submodule_git_dir)) { + return NULL; + } + return submodule_git_dir; +} + static int submodule_needs_pushing(const char *path, const unsigned char sha1[20]) { if (add_submodule_odb(path) || !lookup_commit_reference(sha1)) return 0; + struct strbuf gitdirbuf = STRBUF_INIT; + const char *sm_gitdir = get_submodule_git_dir(path, &gitdirbuf); + if (sm_gitdir == NULL) { + strbuf_release(&gitdirbuf); + return 0; + } if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"rev-list", NULL, "--not", "--remotes", "-n", "1" , NULL}; @@ -535,7 +555,7 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20 argv[1] = sha1_to_hex(sha1); cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, sm_gitdir); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; @@ -551,6 +571,7 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20 return needs_pushing; } + strbuf_release(&gitdirbuf); return 0; } @@ -617,12 +638,18 @@ static int push_submodule(const char *path) if (add_submodule_odb(path)) return 1; + struct strbuf gitdirbuf = STRBUF_INIT; + const char *sm_gitdir = get_submodule_git_dir(path, &gitdirbuf); + if (sm_gitdir == NULL) { + strbuf_release(&gitdirbuf); + return 0; + } if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"push", NULL}; cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, sm_gitdir); cp.git_cmd = 1; cp.no_stdin = 1; cp.dir = path; @@ -631,6 +658,7 @@ static int push_submodule(const char *path) close(cp.out); } + strbuf_release(&gitdirbuf); return 1; } @@ -665,10 +693,16 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20]) struct child_process cp = CHILD_PROCESS_INIT; const char *argv[] = {"rev-list", "-n", "1", NULL, "--not", "--all", NULL}; struct strbuf buf = STRBUF_INIT; + struct strbuf gitdirbuf = STRBUF_INIT; + const char *sm_gitdir = get_submodule_git_dir(path, &gitdirbuf); + if (sm_gitdir == NULL) { + strbuf_release(&gitdirbuf); + return 0; + } argv[3] = sha1_to_hex(sha1); cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, sm_gitdir); cp.git_cmd = 1; cp.no_stdin = 1; cp.dir = path; @@ -676,6 +710,7 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20]) is_present = 1; strbuf_release(&buf); + strbuf_release(&gitdirbuf); } return is_present; } @@ -851,7 +886,7 @@ static int get_next_submodule(struct child_process *cp, if (is_directory(git_dir)) { child_process_init(cp); cp->dir = strbuf_detach(&submodule_path, NULL); - prepare_submodule_repo_env(&cp->env_array); + prepare_submodule_repo_env(&cp->env_array, git_dir); cp->git_cmd = 1; if (!spf->quiet) strbuf_addf(err, "Fetching submodule %s%s\n", @@ -958,15 +993,14 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) strbuf_release(&buf); /* The submodule is not checked out, so it is not modified */ return 0; - } - strbuf_reset(&buf); if (ignore_untracked) argv[2] = "-uno"; cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, git_dir); + strbuf_reset(&buf); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; @@ -1023,11 +1057,11 @@ int submodule_uses_gitfile(const char *path) strbuf_release(&buf); return 0; } - strbuf_release(&buf); /* Now test that all nested submodules use a gitfile too */ cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + prepare_submodule_repo_env(&cp.env_array, git_dir); + strbuf_release(&buf); cp.git_cmd = 1; cp.no_stdin = 1; cp.no_stderr = 1; @@ -1052,6 +1086,7 @@ int ok_to_remove_submodule(const char *path) }; struct strbuf buf = STRBUF_INIT; int ok_to_remove = 1; + const char *git_dir; if (!file_exists(path) || is_empty_dir(path)) return 1; @@ -1060,7 +1095,10 @@ int ok_to_remove_submodule(const char *path) return 0; cp.argv = argv; - prepare_submodule_repo_env(&cp.env_array); + strbuf_addf(&buf, "%s/.git", path); + git_dir = read_gitfile(buf.buf); + prepare_submodule_repo_env(&cp.env_array, git_dir); + strbuf_release(&buf); cp.git_cmd = 1; cp.no_stdin = 1; cp.out = -1; @@ -1272,12 +1310,16 @@ int parallel_submodules(void) return parallel_jobs; } -void prepare_submodule_repo_env(struct argv_array *out) +void prepare_submodule_repo_env(struct argv_array *out, const char* git_dir) { const char * const *var; for (var = local_repo_env; *var; var++) { if (strcmp(*var, CONFIG_DATA_ENVIRONMENT)) argv_array_push(out, *var); + if (strcmp(*var, GIT_DIR_ENVIRONMENT)) + argv_array_pushf(out, "%s=%s", GIT_DIR_ENVIRONMENT, + real_path(git_dir)); } + } diff --git a/submodule.h b/submodule.h index d9e197a..4f8b0c7 100644 --- a/submodule.h +++ b/submodule.h @@ -73,6 +73,6 @@ int parallel_submodules(void); * a submodule by clearing any repo-specific envirionment variables, but * retaining any config in the environment. */ -void prepare_submodule_repo_env(struct argv_array *out); +void prepare_submodule_repo_env(struct argv_array *out, const char *git_dir); On Wed, Aug 31, 2016 at 11:58 AM, Uma Srinivasan <usriniva...@twitter.com> wrote: >> We want to affect only the process we are going to spawn to work >> inside the submodule, not ourselves, which is what this call does; >> this does not sound like a good idea. > > Okay, in that case I would have to pass the "git_dir" as a new > argument to prepare_submodule_repo_env(). I know what to pass from the > is_submodule_modified() caller. I don't think it's all that obvious > for the other callers. > > Thanks, > Uma > > On Wed, Aug 31, 2016 at 11:44 AM, Junio C Hamano <gits...@pobox.com> wrote: >> Uma Srinivasan <usriniva...@twitter.com> writes: >> >>> diff --git a/submodule.c b/submodule.c >>> index 5a62aa2..23443a7 100644 >>> --- a/submodule.c >>> +++ b/submodule.c >>> @@ -960,6 +960,9 @@ unsigned is_submodule_modified(const char *path, >>> int ignore_untracked) >>> return 0; >>> >>> } >>> + /* stuff submodule git dir into env var */ >>> + set_git_dir(git_dir); >> >> We want to affect only the process we are going to spawn to work >> inside the submodule, not ourselves, which is what this call does; >> this does not sound like a good idea. >>