diff options
author | Prathamesh Chavan <pc44800@gmail.com> | 2018-05-08 17:29:49 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-05-09 12:37:00 +0900 |
commit | c033a2f62dda774de8cccc83b7f1918377995d6c (patch) | |
tree | 3f7723b2d6800286553045eae10ed6e08331562d | |
parent | The fifth batch for 2.18 (diff) | |
download | tgif-c033a2f62dda774de8cccc83b7f1918377995d6c.tar.xz |
submodule foreach: correct '$path' in nested submodules from a subdirectory
When running 'git submodule foreach --recursive' from a subdirectory of
your repository, nested submodules get a bogus value for $path:
For a submodule 'sub' that contains a nested submodule 'nested',
running 'git -C dir submodule foreach echo $path' from the root of the
superproject would report path='../nested' for the nested submodule.
The first part '../' is derived from the logic computing the relative
path from $pwd to the root of the superproject. The second part is the
submodule path inside the submodule. This value is of little use and is
hard to document.
Also, in git-submodule.txt, $path is documented to be the "name of the
submodule directory relative to the superproject", but "the
superproject" is ambiguous.
To resolve both these issues, we could:
(a) Change "the superproject" to "its immediate superproject", so
$path would be "nested" instead of "../nested".
(b) Change "the superproject" to "the superproject the original
command was run from", so $path would be "sub/nested" instead of
"../nested".
(c) Change "the superproject" to "the directory the original command
was run from", so $path would be "../sub/nested" instead of
"../nested".
The behavior for (c) was attempted to be introduced in 091a6eb0fe
(submodule: drop the top-level requirement, 2013-06-16) with the intent
for $path to be relative from $pwd to the submodule worktree, but that
did not work for nested submodules, as the intermittent submodules
were not included in the path.
If we were to fix the meaning of the $path using (a), we would break
any existing submodule user that runs foreach from non-root of the
superproject as the non-nested submodule '../sub' would change its
path to 'sub'.
If we were to fix the meaning of $path using (b), then we would break
any user that uses nested submodules (even from the root directory)
as the 'nested' would become 'sub/nested'.
If we were to fix the meaning of $path using (c), then we would break
the same users as in (b) as 'nested' would become 'sub/nested' from
the root directory of the superproject.
All groups can be found in the wild. The author has no data if one group
outweighs the other by large margin, and offending each one seems equally
bad at first. However in the authors imagination it is better to go with
(a) as running from a sub directory sounds like it is carried out by a
human rather than by some automation task. With a human on the keyboard
the feedback loop is short and the changed behavior can be adapted to
quickly unlike some automation that can break silently.
Discussed-with: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Prathamesh Chavan <pc44800@gmail.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-x | git-submodule.sh | 1 | ||||
-rwxr-xr-x | t/t7407-submodule-foreach.sh | 36 |
2 files changed, 34 insertions, 3 deletions
diff --git a/git-submodule.sh b/git-submodule.sh index 24914963ca..331d71c908 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -345,7 +345,6 @@ cmd_foreach() prefix="$prefix$sm_path/" sanitize_submodule_env cd "$sm_path" && - sm_path=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") && # we make $path available to scripts ... path=$sm_path && if test $# -eq 1 diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 6ba5daf42e..5144cc6926 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -82,9 +82,9 @@ test_expect_success 'test basic "submodule foreach" usage' ' cat >expect <<EOF Entering '../sub1' -$pwd/clone-foo1-../sub1-$sub1sha1 +$pwd/clone-foo1-sub1-$sub1sha1 Entering '../sub3' -$pwd/clone-foo3-../sub3-$sub3sha1 +$pwd/clone-foo3-sub3-$sub3sha1 EOF test_expect_success 'test "submodule foreach" from subdirectory' ' @@ -196,6 +196,38 @@ test_expect_success 'test messages from "foreach --recursive" from subdirectory' ) && test_i18ncmp expect actual ' +sub1sha1=$(cd clone2/sub1 && git rev-parse HEAD) +sub2sha1=$(cd clone2/sub2 && git rev-parse HEAD) +sub3sha1=$(cd clone2/sub3 && git rev-parse HEAD) +nested1sha1=$(cd clone2/nested1 && git rev-parse HEAD) +nested2sha1=$(cd clone2/nested1/nested2 && git rev-parse HEAD) +nested3sha1=$(cd clone2/nested1/nested2/nested3 && git rev-parse HEAD) +submodulesha1=$(cd clone2/nested1/nested2/nested3/submodule && git rev-parse HEAD) + +cat >expect <<EOF +Entering '../nested1' +toplevel: $pwd/clone2 name: nested1 path: nested1 hash: $nested1sha1 +Entering '../nested1/nested2' +toplevel: $pwd/clone2/nested1 name: nested2 path: nested2 hash: $nested2sha1 +Entering '../nested1/nested2/nested3' +toplevel: $pwd/clone2/nested1/nested2 name: nested3 path: nested3 hash: $nested3sha1 +Entering '../nested1/nested2/nested3/submodule' +toplevel: $pwd/clone2/nested1/nested2/nested3 name: submodule path: submodule hash: $submodulesha1 +Entering '../sub1' +toplevel: $pwd/clone2 name: foo1 path: sub1 hash: $sub1sha1 +Entering '../sub2' +toplevel: $pwd/clone2 name: foo2 path: sub2 hash: $sub2sha1 +Entering '../sub3' +toplevel: $pwd/clone2 name: foo3 path: sub3 hash: $sub3sha1 +EOF + +test_expect_success 'test "submodule foreach --recursive" from subdirectory' ' + ( + cd clone2/untracked && + git submodule foreach --recursive "echo toplevel: \$toplevel name: \$name path: \$sm_path hash: \$sha1" >../../actual + ) && + test_i18ncmp expect actual +' cat > expect <<EOF nested1-nested1 |