From f1c0368da4d64f394e4c099cb3c232671040d725 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 31 Aug 2021 09:12:56 -0400 Subject: diff --submodule=diff: do not fail on ever-initialied deleted submodules If you have ever initialized a submodule, open_submodule will open it. If you then delete the submodule's worktree directory (but don't remove it from .gitmodules), git diff --submodule=diff would error out as it attempted to chdir into the now-deleted working tree directory. This only matters if the submodules git dir is absorbed. If not, then we no longer have anywhere to run the diff. But that case does not trigger this error, because in that case, open_submodule fails, so we don't resolve a left commit, so we exit early, which is the only thing we could do. If absorbed, then we can run the diff from the submodule's absorbed git dir (.git/modules/sm2). In practice, that's a bit more complicated, because `git diff` expects to be run from inside a working directory, not a git dir. So it looks in the config for core.worktree, and does chdir("../../../sm2"), which is the very dir that we're trying to avoid visiting because it's been deleted. We work around this by setting GIT_WORK_TREE (and GIT_DIR) to ".". It is little weird to set GIT_WORK_TREE to something that is not a working tree just to avoid an unnecessary chdir, but it works. Signed-off-by: David Turner --- submodule.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'submodule.c') diff --git a/submodule.c b/submodule.c index 0b1d9c1dde..8aeff95cfd 100644 --- a/submodule.c +++ b/submodule.c @@ -710,6 +710,16 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path, strvec_push(&cp.args, oid_to_hex(new_oid)); prepare_submodule_repo_env(&cp.env_array); + + if (!is_directory(path)) { + /* fall back to absorbed git dir, if any */ + if (!sub) + goto done; + cp.dir = sub->gitdir; + strvec_push(&cp.env_array, GIT_DIR_ENVIRONMENT "=."); + strvec_push(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT "=."); + } + if (start_command(&cp)) diff_emit_submodule_error(o, "(diff failed)\n"); -- cgit v1.2.3 From 67f61efbb92dce64b33c3280b89e9f253a34df1c Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 31 Aug 2021 09:12:57 -0400 Subject: diff --submodule=diff: don't print failure message twice When we fail to start a diff command inside a submodule, immediately exit the routine rather than trying to finish the command and printing a second message. Signed-off-by: David Turner Signed-off-by: Junio C Hamano --- submodule.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'submodule.c') diff --git a/submodule.c b/submodule.c index 8aeff95cfd..ab5f050f0e 100644 --- a/submodule.c +++ b/submodule.c @@ -720,8 +720,10 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path, strvec_push(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT "=."); } - if (start_command(&cp)) + if (start_command(&cp)) { diff_emit_submodule_error(o, "(diff failed)\n"); + goto done; + } while (strbuf_getwholeline_fd(&sb, cp.out, '\n') != EOF) diff_emit_submodule_pipethrough(o, sb.buf, sb.len); -- cgit v1.2.3