git/t/t7407-submodule-foreach.sh

415 строки
12 KiB
Bash
Исходник Обычный вид История

#!/bin/sh
#
# Copyright (c) 2009 Johan Herland
#
test_description='Test "git submodule foreach"
This test verifies that "git submodule foreach" correctly visits all submodules
that are currently checked out.
'
. ./test-lib.sh
test_expect_success 'setup a submodule tree' '
echo file > file &&
git add file &&
test_tick &&
git commit -m upstream &&
git clone . super &&
git clone super submodule &&
(
cd super &&
git submodule add ../submodule sub1 &&
git submodule add ../submodule sub2 &&
git submodule add ../submodule sub3 &&
git config -f .gitmodules --rename-section \
submodule.sub1 submodule.foo1 &&
git config -f .gitmodules --rename-section \
submodule.sub2 submodule.foo2 &&
git config -f .gitmodules --rename-section \
submodule.sub3 submodule.foo3 &&
git add .gitmodules &&
test_tick &&
git commit -m "submodules" &&
git submodule init sub1 &&
git submodule init sub2 &&
git submodule init sub3
) &&
(
cd submodule &&
echo different > file &&
git add file &&
test_tick &&
git commit -m "different"
) &&
(
cd super &&
(
cd sub3 &&
git pull
) &&
git add sub3 &&
test_tick &&
git commit -m "update sub3"
)
'
sub1sha1=$(cd super/sub1 && git rev-parse HEAD)
sub3sha1=$(cd super/sub3 && git rev-parse HEAD)
git-submodule foreach: Add $toplevel variable Add a $toplevel variable accessible to `git submodule foreach`, it contains the absolute path of the top level directory (where .gitmodules is). This makes it possible to e.g. read data in .gitmodules from within foreach commands. I'm using this to configure the branch names I want to track for each submodule: git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' For a little history: This patch is borne out of my continuing fight of trying to have Git track the branches of submodules, not just their commits. Obviously that's not how they work (they only track commits), but I'm just interested in being able to do: git submodule foreach 'git pull' Of course that won't work because the submodule is in a disconnected head, so I first have to connect it, but connect it *to what*. For a while I was happy with this because as fate had it, it just so happened to do what I meant: git submodule foreach 'git checkout $(git describe --all --always) && git pull' But then that broke down, if there's a tag and a branch the tag will win out, and I can't git pull a branch: $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master $ git tag -l release-0.0.6 $ git describe --always --all release-0.0.6 So I figured that I might as well start tracking the branches I want in .gitmodules itself: [submodule "yaml-mode"] path = yaml-mode url = git://github.com/yoshiki/yaml-mode.git branch = master So now I can just do (as stated above): git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' Maybe there's a less painful way to do *that* (I'd love to hear about it). But regardless of that I think it's a good idea to be able to know what the top-level is from git submodule foreach. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-05-21 20:10:10 +04:00
pwd=$(pwd)
cat > expect <<EOF
Entering 'sub1'
git-submodule foreach: Add $toplevel variable Add a $toplevel variable accessible to `git submodule foreach`, it contains the absolute path of the top level directory (where .gitmodules is). This makes it possible to e.g. read data in .gitmodules from within foreach commands. I'm using this to configure the branch names I want to track for each submodule: git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' For a little history: This patch is borne out of my continuing fight of trying to have Git track the branches of submodules, not just their commits. Obviously that's not how they work (they only track commits), but I'm just interested in being able to do: git submodule foreach 'git pull' Of course that won't work because the submodule is in a disconnected head, so I first have to connect it, but connect it *to what*. For a while I was happy with this because as fate had it, it just so happened to do what I meant: git submodule foreach 'git checkout $(git describe --all --always) && git pull' But then that broke down, if there's a tag and a branch the tag will win out, and I can't git pull a branch: $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master $ git tag -l release-0.0.6 $ git describe --always --all release-0.0.6 So I figured that I might as well start tracking the branches I want in .gitmodules itself: [submodule "yaml-mode"] path = yaml-mode url = git://github.com/yoshiki/yaml-mode.git branch = master So now I can just do (as stated above): git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' Maybe there's a less painful way to do *that* (I'd love to hear about it). But regardless of that I think it's a good idea to be able to know what the top-level is from git submodule foreach. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-05-21 20:10:10 +04:00
$pwd/clone-foo1-sub1-$sub1sha1
Entering 'sub3'
git-submodule foreach: Add $toplevel variable Add a $toplevel variable accessible to `git submodule foreach`, it contains the absolute path of the top level directory (where .gitmodules is). This makes it possible to e.g. read data in .gitmodules from within foreach commands. I'm using this to configure the branch names I want to track for each submodule: git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' For a little history: This patch is borne out of my continuing fight of trying to have Git track the branches of submodules, not just their commits. Obviously that's not how they work (they only track commits), but I'm just interested in being able to do: git submodule foreach 'git pull' Of course that won't work because the submodule is in a disconnected head, so I first have to connect it, but connect it *to what*. For a while I was happy with this because as fate had it, it just so happened to do what I meant: git submodule foreach 'git checkout $(git describe --all --always) && git pull' But then that broke down, if there's a tag and a branch the tag will win out, and I can't git pull a branch: $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master $ git tag -l release-0.0.6 $ git describe --always --all release-0.0.6 So I figured that I might as well start tracking the branches I want in .gitmodules itself: [submodule "yaml-mode"] path = yaml-mode url = git://github.com/yoshiki/yaml-mode.git branch = master So now I can just do (as stated above): git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' Maybe there's a less painful way to do *that* (I'd love to hear about it). But regardless of that I think it's a good idea to be able to know what the top-level is from git submodule foreach. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-05-21 20:10:10 +04:00
$pwd/clone-foo3-sub3-$sub3sha1
EOF
test_expect_success 'test basic "submodule foreach" usage' '
git clone super clone &&
(
cd clone &&
git submodule update --init -- sub1 sub3 &&
git-submodule foreach: Add $toplevel variable Add a $toplevel variable accessible to `git submodule foreach`, it contains the absolute path of the top level directory (where .gitmodules is). This makes it possible to e.g. read data in .gitmodules from within foreach commands. I'm using this to configure the branch names I want to track for each submodule: git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' For a little history: This patch is borne out of my continuing fight of trying to have Git track the branches of submodules, not just their commits. Obviously that's not how they work (they only track commits), but I'm just interested in being able to do: git submodule foreach 'git pull' Of course that won't work because the submodule is in a disconnected head, so I first have to connect it, but connect it *to what*. For a while I was happy with this because as fate had it, it just so happened to do what I meant: git submodule foreach 'git checkout $(git describe --all --always) && git pull' But then that broke down, if there's a tag and a branch the tag will win out, and I can't git pull a branch: $ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/master $ git tag -l release-0.0.6 $ git describe --always --all release-0.0.6 So I figured that I might as well start tracking the branches I want in .gitmodules itself: [submodule "yaml-mode"] path = yaml-mode url = git://github.com/yoshiki/yaml-mode.git branch = master So now I can just do (as stated above): git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull' Maybe there's a less painful way to do *that* (I'd love to hear about it). But regardless of that I think it's a good idea to be able to know what the top-level is from git submodule foreach. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-05-21 20:10:10 +04:00
git submodule foreach "echo \$toplevel-\$name-\$path-\$sha1" > ../actual &&
git config foo.bar zar &&
git submodule foreach "git config --file \"\$toplevel/.git/config\" foo.bar"
) &&
test_i18ncmp expect actual
'
cat >expect <<EOF
Entering '../sub1'
$pwd/clone-foo1-sub1-../sub1-$sub1sha1
Entering '../sub3'
$pwd/clone-foo3-sub3-../sub3-$sub3sha1
EOF
test_expect_success 'test "submodule foreach" from subdirectory' '
mkdir clone/sub &&
(
cd clone/sub &&
git submodule foreach "echo \$toplevel-\$name-\$sm_path-\$displaypath-\$sha1" >../../actual
) &&
test_i18ncmp expect actual
'
test_expect_success 'setup nested submodules' '
git clone submodule nested1 &&
git clone submodule nested2 &&
git clone submodule nested3 &&
(
cd nested3 &&
git submodule add ../submodule submodule &&
test_tick &&
git commit -m "submodule" &&
git submodule init submodule
) &&
(
cd nested2 &&
git submodule add ../nested3 nested3 &&
test_tick &&
git commit -m "nested3" &&
git submodule init nested3
) &&
(
cd nested1 &&
git submodule add ../nested2 nested2 &&
test_tick &&
git commit -m "nested2" &&
git submodule init nested2
) &&
(
cd super &&
git submodule add ../nested1 nested1 &&
test_tick &&
git commit -m "nested1" &&
git submodule init nested1
)
'
test_expect_success 'use "submodule foreach" to checkout 2nd level submodule' '
git clone super clone2 &&
(
cd clone2 &&
test_must_fail git rev-parse --resolve-git-dir sub1/.git &&
test_must_fail git rev-parse --resolve-git-dir sub2/.git &&
test_must_fail git rev-parse --resolve-git-dir sub3/.git &&
test_must_fail git rev-parse --resolve-git-dir nested1/.git &&
git submodule update --init &&
git rev-parse --resolve-git-dir sub1/.git &&
git rev-parse --resolve-git-dir sub2/.git &&
git rev-parse --resolve-git-dir sub3/.git &&
git rev-parse --resolve-git-dir nested1/.git &&
test_must_fail git rev-parse --resolve-git-dir nested1/nested2/.git &&
git submodule foreach "git submodule update --init" &&
git rev-parse --resolve-git-dir nested1/nested2/.git &&
test_must_fail git rev-parse --resolve-git-dir nested1/nested2/nested3/.git
)
'
test_expect_success 'use "foreach --recursive" to checkout all submodules' '
(
cd clone2 &&
git submodule foreach --recursive "git submodule update --init" &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git
)
'
cat > expect <<EOF
Entering 'nested1'
Entering 'nested1/nested2'
Entering 'nested1/nested2/nested3'
Entering 'nested1/nested2/nested3/submodule'
Entering 'sub1'
Entering 'sub2'
Entering 'sub3'
EOF
test_expect_success 'test messages from "foreach --recursive"' '
(
cd clone2 &&
git submodule foreach --recursive "true" > ../actual
) &&
test_i18ncmp expect actual
'
cat > expect <<EOF
Entering '../nested1'
Entering '../nested1/nested2'
Entering '../nested1/nested2/nested3'
Entering '../nested1/nested2/nested3/submodule'
Entering '../sub1'
Entering '../sub2'
Entering '../sub3'
EOF
test_expect_success 'test messages from "foreach --recursive" from subdirectory' '
(
cd clone2 &&
mkdir untracked &&
cd untracked &&
git submodule foreach --recursive >../../actual
) &&
test_i18ncmp expect actual
'
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>
2018-05-09 03:29:49 +03:00
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 displaypath: ../nested1 hash: $nested1sha1
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>
2018-05-09 03:29:49 +03:00
Entering '../nested1/nested2'
toplevel: $pwd/clone2/nested1 name: nested2 path: nested2 displaypath: ../nested1/nested2 hash: $nested2sha1
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>
2018-05-09 03:29:49 +03:00
Entering '../nested1/nested2/nested3'
toplevel: $pwd/clone2/nested1/nested2 name: nested3 path: nested3 displaypath: ../nested1/nested2/nested3 hash: $nested3sha1
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>
2018-05-09 03:29:49 +03:00
Entering '../nested1/nested2/nested3/submodule'
toplevel: $pwd/clone2/nested1/nested2/nested3 name: submodule path: submodule displaypath: ../nested1/nested2/nested3/submodule hash: $submodulesha1
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>
2018-05-09 03:29:49 +03:00
Entering '../sub1'
toplevel: $pwd/clone2 name: foo1 path: sub1 displaypath: ../sub1 hash: $sub1sha1
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>
2018-05-09 03:29:49 +03:00
Entering '../sub2'
toplevel: $pwd/clone2 name: foo2 path: sub2 displaypath: ../sub2 hash: $sub2sha1
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>
2018-05-09 03:29:49 +03:00
Entering '../sub3'
toplevel: $pwd/clone2 name: foo3 path: sub3 displaypath: ../sub3 hash: $sub3sha1
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>
2018-05-09 03:29:49 +03:00
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 displaypath: \$displaypath hash: \$sha1" >../../actual
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>
2018-05-09 03:29:49 +03:00
) &&
test_i18ncmp expect actual
'
cat > expect <<EOF
nested1-nested1
nested2-nested2
nested3-nested3
submodule-submodule
foo1-sub1
foo2-sub2
foo3-sub3
EOF
test_expect_success 'test "foreach --quiet --recursive"' '
(
cd clone2 &&
git submodule foreach -q --recursive "echo \$name-\$path" > ../actual
) &&
test_cmp expect actual
'
test_expect_success 'use "update --recursive" to checkout all submodules' '
git clone super clone3 &&
(
cd clone3 &&
test_must_fail git rev-parse --resolve-git-dir sub1/.git &&
test_must_fail git rev-parse --resolve-git-dir sub2/.git &&
test_must_fail git rev-parse --resolve-git-dir sub3/.git &&
test_must_fail git rev-parse --resolve-git-dir nested1/.git &&
git submodule update --init --recursive &&
git rev-parse --resolve-git-dir sub1/.git &&
git rev-parse --resolve-git-dir sub2/.git &&
git rev-parse --resolve-git-dir sub3/.git &&
git rev-parse --resolve-git-dir nested1/.git &&
git rev-parse --resolve-git-dir nested1/nested2/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git
)
'
nested1sha1=$(cd clone3/nested1 && git rev-parse HEAD)
nested2sha1=$(cd clone3/nested1/nested2 && git rev-parse HEAD)
nested3sha1=$(cd clone3/nested1/nested2/nested3 && git rev-parse HEAD)
submodulesha1=$(cd clone3/nested1/nested2/nested3/submodule && git rev-parse HEAD)
sub1sha1=$(cd clone3/sub1 && git rev-parse HEAD)
sub2sha1=$(cd clone3/sub2 && git rev-parse HEAD)
sub3sha1=$(cd clone3/sub3 && git rev-parse HEAD)
sub1sha1_short=$(cd clone3/sub1 && git rev-parse --short HEAD)
sub2sha1_short=$(cd clone3/sub2 && git rev-parse --short HEAD)
cat > expect <<EOF
$nested1sha1 nested1 (heads/master)
$nested2sha1 nested1/nested2 (heads/master)
$nested3sha1 nested1/nested2/nested3 (heads/master)
$submodulesha1 nested1/nested2/nested3/submodule (heads/master)
$sub1sha1 sub1 ($sub1sha1_short)
$sub2sha1 sub2 ($sub2sha1_short)
$sub3sha1 sub3 (heads/master)
EOF
test_expect_success 'test "status --recursive"' '
(
cd clone3 &&
git submodule status --recursive > ../actual
) &&
test_cmp expect actual
'
cat > expect <<EOF
$nested1sha1 nested1 (heads/master)
+$nested2sha1 nested1/nested2 (file2~1)
$nested3sha1 nested1/nested2/nested3 (heads/master)
$submodulesha1 nested1/nested2/nested3/submodule (heads/master)
EOF
test_expect_success 'ensure "status --cached --recursive" preserves the --cached flag' '
(
cd clone3 &&
(
cd nested1/nested2 &&
test_commit file2
) &&
git submodule status --cached --recursive -- nested1 > ../actual
) &&
test_cmp expect actual
'
submodule status: correct path handling in recursive submodules The new test which is a replica of the previous test except that it executes from a sub directory. Prior to this patch the test failed by having too many '../' prefixed: --- expect 2016-03-29 19:02:33.087336115 +0000 +++ actual 2016-03-29 19:02:33.359343311 +0000 @@ -1,7 +1,7 @@ b23f134787d96fae589a6b76da41f4db112fc8db ../nested1 (heads/master) -+25d56d1ddfb35c3e91ff7d8f12331c2e53147dcc ../nested1/nested2 (file2) - 5ec83512b76a0b8170b899f8e643913c3e9b72d9 ../nested1/nested2/nested3 (heads/master) - 509f622a4f36a3e472affcf28fa959174f3dd5b5 ../nested1/nested2/nested3/submodule (heads/master) ++25d56d1ddfb35c3e91ff7d8f12331c2e53147dcc ../../nested1/nested2 (file2) + 5ec83512b76a0b8170b899f8e643913c3e9b72d9 ../../../nested1/nested2/nested3 (heads/master) + 509f622a4f36a3e472affcf28fa959174f3dd5b5 ../../../../nested1/nested2/nested3/submodule (heads/master) 0c90624ab7f1aaa301d3bb79f60dcfed1ec4897f ../sub1 (0c90624) 0c90624ab7f1aaa301d3bb79f60dcfed1ec4897f ../sub2 (0c90624) 509f622a4f36a3e472affcf28fa959174f3dd5b5 ../sub3 (heads/master) The path code in question: displaypath=$(relative_path "$prefix$sm_path") prefix=$displaypath if recursive: eval cmd_status That way we change `prefix` each iteration to contain another '../', because of the the relative_path computation is done on an already computed relative path. We must call relative_path exactly once with `wt_prefix` non empty. Further calls in recursive instances to to calculate the displaypath already incorporate the correct prefix from before. Fix the issue by clearing `wt_prefix` in recursive calls. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-03-30 04:27:43 +03:00
nested2sha1=$(git -C clone3/nested1/nested2 rev-parse HEAD)
cat > expect <<EOF
$nested1sha1 ../nested1 (heads/master)
+$nested2sha1 ../nested1/nested2 (file2)
$nested3sha1 ../nested1/nested2/nested3 (heads/master)
$submodulesha1 ../nested1/nested2/nested3/submodule (heads/master)
$sub1sha1 ../sub1 ($sub1sha1_short)
$sub2sha1 ../sub2 ($sub2sha1_short)
$sub3sha1 ../sub3 (heads/master)
EOF
test_expect_success 'test "status --recursive" from sub directory' '
(
cd clone3 &&
mkdir tmp && cd tmp &&
git submodule status --recursive > ../../actual
) &&
test_cmp expect actual
'
test_expect_success 'use "git clone --recursive" to checkout all submodules' '
git clone --recursive super clone4 &&
(
cd clone4 &&
git rev-parse --resolve-git-dir .git &&
git rev-parse --resolve-git-dir sub1/.git &&
git rev-parse --resolve-git-dir sub2/.git &&
git rev-parse --resolve-git-dir sub3/.git &&
git rev-parse --resolve-git-dir nested1/.git &&
git rev-parse --resolve-git-dir nested1/nested2/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git
)
'
test_expect_success 'test "update --recursive" with a flag with spaces' '
git clone super "common objects" &&
git clone super clone5 &&
(
cd clone5 &&
test_must_fail git rev-parse --resolve-git-dir d nested1/.git &&
git submodule update --init --recursive --reference="$(dirname "$PWD")/common objects" &&
git rev-parse --resolve-git-dir nested1/.git &&
git rev-parse --resolve-git-dir nested1/nested2/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/.git &&
test -f .git/modules/nested1/objects/info/alternates &&
test -f .git/modules/nested1/modules/nested2/objects/info/alternates &&
test -f .git/modules/nested1/modules/nested2/modules/nested3/objects/info/alternates
)
'
test_expect_success 'use "update --recursive nested1" to checkout all submodules rooted in nested1' '
git clone super clone6 &&
(
cd clone6 &&
test_must_fail git rev-parse --resolve-git-dir sub1/.git &&
test_must_fail git rev-parse --resolve-git-dir sub2/.git &&
test_must_fail git rev-parse --resolve-git-dir sub3/.git &&
test_must_fail git rev-parse --resolve-git-dir nested1/.git &&
git submodule update --init --recursive -- nested1 &&
test_must_fail git rev-parse --resolve-git-dir sub1/.git &&
test_must_fail git rev-parse --resolve-git-dir sub2/.git &&
test_must_fail git rev-parse --resolve-git-dir sub3/.git &&
git rev-parse --resolve-git-dir nested1/.git &&
git rev-parse --resolve-git-dir nested1/nested2/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/.git &&
git rev-parse --resolve-git-dir nested1/nested2/nested3/submodule/.git
)
'
git-submodule.sh: preserve stdin for the command spawned by foreach The user-supplied command spawned by 'submodule foreach' loses its connection to the original standard input. Instead, it is connected to the output of a pipe within the git-submodule script. The user-supplied command supplied to 'submodule foreach' is spawned within a while loop which is being piped into. Due to the way shells implement piping output to a while loop, a subshell is created with its standard input attached to the output of the pipe. This results in all of the commands executed within the while loop to have their stdins modified in the same way, including the user-supplied command. This can cause a problem if the command requires reading from stdin or if it changes its behavior based on whether stdin is a tty or not. For example, this problem was noticed when trying to execute the following: git submodule foreach git shortlog --since=two.weeks.ago which printed a message about entering the first submodule and produced no further output and exited with a status of zero. In this case, shortlog detected that it was not connected to a tty, and since no revision was supplied as an argument, it attempted to read the list of revisions from standard input. Instead, it slurped up the list of submodules that was being piped to the enclosing while loop and caused that loop to end early without processing the remaining submodules. Work around this behavior by saving the original standard input file descriptor before the while loop, and restoring it when spawning the user-supplied command. This fixes the tests in t7407. Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-06-30 04:34:58 +04:00
test_expect_success 'command passed to foreach retains notion of stdin' '
(
cd super &&
git submodule foreach echo success >../expected &&
yes | git submodule foreach "read y && test \"x\$y\" = xy && echo success" >../actual
) &&
test_cmp expected actual
'
git-submodule.sh: preserve stdin for the command spawned by foreach The user-supplied command spawned by 'submodule foreach' loses its connection to the original standard input. Instead, it is connected to the output of a pipe within the git-submodule script. The user-supplied command supplied to 'submodule foreach' is spawned within a while loop which is being piped into. Due to the way shells implement piping output to a while loop, a subshell is created with its standard input attached to the output of the pipe. This results in all of the commands executed within the while loop to have their stdins modified in the same way, including the user-supplied command. This can cause a problem if the command requires reading from stdin or if it changes its behavior based on whether stdin is a tty or not. For example, this problem was noticed when trying to execute the following: git submodule foreach git shortlog --since=two.weeks.ago which printed a message about entering the first submodule and produced no further output and exited with a status of zero. In this case, shortlog detected that it was not connected to a tty, and since no revision was supplied as an argument, it attempted to read the list of revisions from standard input. Instead, it slurped up the list of submodules that was being piped to the enclosing while loop and caused that loop to end early without processing the remaining submodules. Work around this behavior by saving the original standard input file descriptor before the while loop, and restoring it when spawning the user-supplied command. This fixes the tests in t7407. Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-06-30 04:34:58 +04:00
test_expect_success 'command passed to foreach --recursive retains notion of stdin' '
(
cd clone2 &&
git submodule foreach --recursive echo success >../expected &&
yes | git submodule foreach --recursive "read y && test \"x\$y\" = xy && echo success" >../actual
) &&
test_cmp expected actual
'
test_expect_success 'multi-argument command passed to foreach is not shell-evaluated twice' '
(
cd super &&
git submodule foreach "echo \\\"quoted\\\"" > ../expected &&
git submodule foreach echo \"quoted\" > ../actual
) &&
test_cmp expected actual
'
test_done