submodule: drop the top-level requirement

Use the new rev-parse --prefix option to process all paths given to the submodule command, dropping the requirement that it be run from the top-level of the repository. Since the interpretation of a relative submodule URL depends on whether or not "remote.origin.url" is configured, explicitly block relative URLs in "git submodule add" when not at the top level of the working tree. Signed-off-by: John Keeping <john@keeping.me.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

John Keeping committed Jun 16, 2013 at 15:18 UTC 091a6eb0feed820a43663ca63dc2bc0bb247bbae
6 files changed +319 -35
git-submodule.sh
+100 -35
@@ -14,10 +14,13 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re
14 or: $dashless [--quiet] foreach [--recursive] <command>
15 or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
16 OPTIONS_SPEC=
17 +SUBDIRECTORY_OK=Yes
18 . git-sh-setup
19 . git-sh-i18n
20 . git-parse-remote
21 require_work_tree
22 +wt_prefix=$(git rev-parse --show-prefix)
23 +cd_to_toplevel
24
25 command=
26 branch=
@@ -106,12 +109,48 @@ resolve_relative_url ()
109 echo "${is_relative:+${up_path}}${remoteurl#./}"
110 }
111
112 +# Resolve a path to be relative to another path. This is intended for
113 +# converting submodule paths when git-submodule is run in a subdirectory
114 +# and only handles paths where the directory separator is '/'.
115 +#
116 +# The output is the first argument as a path relative to the second argument,
117 +# which defaults to $wt_prefix if it is omitted.
118 +relative_path ()
119 +{
120 + local target curdir result
121 + target=$1
122 + curdir=${2-$wt_prefix}
123 + curdir=${curdir%/}
124 + result=
125 +
126 + while test -n "$curdir"
127 + do
128 + case "$target" in
129 + "$curdir/"*)
130 + target=${target#"$curdir"/}
131 + break
132 + ;;
133 + esac
134 +
135 + result="${result}../"
136 + if test "$curdir" = "${curdir%/*}"
137 + then
138 + curdir=
139 + else
140 + curdir="${curdir%/*}"
141 + fi
142 + done
143 +
144 + echo "$result$target"
145 +}
146 +
147 #
148 # Get submodule info for registered submodules
149 # $@ = path to limit submodule list
150 #
151 module_list()
152 {
153 + eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
154 (
155 git ls-files --error-unmatch --stage -- "$@" ||
156 echo "unmatched pathspec exists"
@@ -282,6 +321,7 @@ isnumber()
321 cmd_add()
322 {
323 # parse $args after "submodule ... add".
324 + reference_path=
325 while test $# -ne 0
326 do
327 case "$1" in
@@ -298,11 +338,11 @@ cmd_add()
338 ;;
339 --reference)
340 case "$2" in '') usage ;; esac
301 - reference="--reference=$2"
341 + reference_path=$2
342 shift
343 ;;
344 --reference=*)
305 - reference="$1"
345 + reference_path="${1#--reference=}"
346 ;;
347 --name)
348 case "$2" in '') usage ;; esac
@@ -323,6 +363,14 @@ cmd_add()
363 shift
364 done
365
366 + if test -n "$reference_path"
367 + then
368 + is_absolute_path "$reference_path" ||
369 + reference_path="$wt_prefix$reference_path"
370 +
371 + reference="--reference=$reference_path"
372 + fi
373 +
374 repo=$1
375 sm_path=$2
376
@@ -335,9 +383,14 @@ cmd_add()
383 usage
384 fi
385
386 + is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
387 +
388 # assure repo is absolute or relative to parent
389 case "$repo" in
390 ./*|../*)
391 + test -z "$wt_prefix" ||
392 + die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
393 +
394 # dereference source url relative to parent's url
395 realrepo=$(resolve_relative_url "$repo") || exit
396 ;;
@@ -471,21 +524,23 @@ cmd_foreach()
524 die_if_unmatched "$mode"
525 if test -e "$sm_path"/.git
526 then
474 - say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
527 + displaypath=$(relative_path "$sm_path")
528 + say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
529 name=$(module_name "$sm_path")
530 (
531 prefix="$prefix$sm_path/"
532 clear_local_git_env
479 - # we make $path available to scripts ...
480 - path=$sm_path
533 cd "$sm_path" &&
534 + sm_path=$(relative_path "$sm_path") &&
535 + # we make $path available to scripts ...
536 + path=$sm_path &&
537 eval "$@" &&
538 if test -n "$recursive"
539 then
540 cmd_foreach "--recursive" "$@"
541 fi
542 ) <&3 3<&- ||
488 - die "$(eval_gettext "Stopping at '\$prefix\$sm_path'; script returned non-zero status.")"
543 + die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
544 fi
545 done
546 }
@@ -524,12 +579,14 @@ cmd_init()
579 die_if_unmatched "$mode"
580 name=$(module_name "$sm_path") || exit
581
582 + displaypath=$(relative_path "$sm_path")
583 +
584 # Copy url setting when it is not set yet
585 if test -z "$(git config "submodule.$name.url")"
586 then
587 url=$(git config -f .gitmodules submodule."$name".url)
588 test -z "$url" &&
532 - die "$(eval_gettext "No url found for submodule path '\$sm_path' in .gitmodules")"
589 + die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
590
591 # Possibly a url relative to parent
592 case "$url" in
@@ -538,9 +595,9 @@ cmd_init()
595 ;;
596 esac
597 git config submodule."$name".url "$url" ||
541 - die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
598 + die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
599
543 - say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
600 + say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
601 fi
602
603 # Copy "update" setting when it is not set yet
@@ -548,7 +605,7 @@ cmd_init()
605 test -z "$upd" ||
606 test -n "$(git config submodule."$name".update)" ||
607 git config submodule."$name".update "$upd" ||
551 - die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
608 + die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
609 done
610 }
611
@@ -594,27 +651,29 @@ cmd_deinit()
651 die_if_unmatched "$mode"
652 name=$(module_name "$sm_path") || exit
653
654 + displaypath=$(relative_path "$sm_path")
655 +
656 # Remove the submodule work tree (unless the user already did it)
657 if test -d "$sm_path"
658 then
659 # Protect submodules containing a .git directory
660 if test -d "$sm_path/.git"
661 then
603 - echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
662 + echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
663 die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
664 fi
665
666 if test -z "$force"
667 then
668 git rm -qn "$sm_path" ||
610 - die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
669 + die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
670 fi
671 rm -rf "$sm_path" &&
613 - say "$(eval_gettext "Cleared directory '\$sm_path'")" ||
614 - say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
672 + say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
673 + say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
674 fi
675
617 - mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
676 + mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
677
678 # Remove the .git/config entries (unless the user already did it)
679 if test -n "$(git config --get-regexp submodule."$name\.")"
@@ -623,7 +682,7 @@ cmd_deinit()
682 # the user later decides to init this submodule again
683 url=$(git config submodule."$name".url)
684 git config --remove-section submodule."$name" 2>/dev/null &&
626 - say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
685 + say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
686 fi
687 done
688 }
@@ -717,9 +776,11 @@ cmd_update()
776 update_module=$(git config submodule."$name".update)
777 fi
778
779 + displaypath=$(relative_path "$prefix$sm_path")
780 +
781 if test "$update_module" = "none"
782 then
722 - echo "Skipping submodule '$prefix$sm_path'"
783 + echo "Skipping submodule '$displaypath'"
784 continue
785 fi
786
@@ -728,7 +789,7 @@ cmd_update()
789 # Only mention uninitialized submodules when its
790 # path have been specified
791 test "$#" != "0" &&
731 - say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
792 + say "$(eval_gettext "Submodule path '\$displaypath' not initialized
793 Maybe you want to use 'update --init'?")"
794 continue
795 fi
@@ -741,7 +802,7 @@ Maybe you want to use 'update --init'?")"
802 else
803 subsha1=$(clear_local_git_env; cd "$sm_path" &&
804 git rev-parse --verify HEAD) ||
744 - die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
805 + die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
806 fi
807
808 if test -n "$remote"
@@ -774,7 +835,7 @@ Maybe you want to use 'update --init'?")"
835 (clear_local_git_env; cd "$sm_path" &&
836 ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
837 test -z "$rev") || git-fetch)) ||
777 - die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
838 + die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
839 fi
840
841 # Is this something we just cloned?
@@ -788,20 +849,20 @@ Maybe you want to use 'update --init'?")"
849 case "$update_module" in
850 rebase)
851 command="git rebase"
791 - die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
792 - say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
852 + die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
853 + say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
854 must_die_on_failure=yes
855 ;;
856 merge)
857 command="git merge"
797 - die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
798 - say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
858 + die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
859 + say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
860 must_die_on_failure=yes
861 ;;
862 *)
863 command="git checkout $subforce -q"
803 - die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
804 - say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
864 + die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
865 + say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
866 ;;
867 esac
868
@@ -828,7 +889,7 @@ Maybe you want to use 'update --init'?")"
889 res=$?
890 if test $res -gt 0
891 then
831 - die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
892 + die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
893 if test $res -eq 1
894 then
895 err="${err};$die_msg"
@@ -942,6 +1003,7 @@ cmd_summary() {
1003 fi
1004
1005 cd_to_toplevel
1006 + eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
1007 # Get modified modules cared by user
1008 modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
1009 sane_egrep '^:([0-7]* )?160000' |
@@ -991,16 +1053,18 @@ cmd_summary() {
1053 ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
1054 missing_dst=t
1055
1056 + display_name=$(relative_path "$name")
1057 +
1058 total_commits=
1059 case "$missing_src,$missing_dst" in
1060 t,)
997 - errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_src")"
1061 + errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_src")"
1062 ;;
1063 ,t)
1000 - errmsg="$(eval_gettext " Warn: \$name doesn't contain commit \$sha1_dst")"
1064 + errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_dst")"
1065 ;;
1066 t,t)
1003 - errmsg="$(eval_gettext " Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
1067 + errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
1068 ;;
1069 *)
1070 errmsg=
@@ -1029,12 +1093,12 @@ cmd_summary() {
1093 submodule="$(gettext "submodule")"
1094 if test $mod_dst = 160000
1095 then
1032 - echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
1096 + echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
1097 else
1034 - echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
1098 + echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
1099 fi
1100 else
1037 - echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
1101 + echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
1102 fi
1103 if test -n "$errmsg"
1104 then
@@ -1118,7 +1182,7 @@ cmd_status()
1182 die_if_unmatched "$mode"
1183 name=$(module_name "$sm_path") || exit
1184 url=$(git config submodule."$name".url)
1121 - displaypath="$prefix$sm_path"
1185 + displaypath=$(relative_path "$prefix$sm_path")
1186 if test "$stage" = U
1187 then
1188 say "U$sha1 $displaypath"
@@ -1213,7 +1277,8 @@ cmd_sync()
1277
1278 if git config "submodule.$name.url" >/dev/null 2>/dev/null
1279 then
1216 - say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
1280 + displaypath=$(relative_path "$prefix$sm_path")
1281 + say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
1282 git config submodule."$name".url "$super_config_url"
1283
1284 if test -e "$sm_path"/.git
t/t7400-submodule-basic.sh
+80
@@ -212,6 +212,32 @@ test_expect_success 'submodule add with ./, /.. and // in path' '
212 test_cmp empty untracked
213 '
214
215 +test_expect_success 'submodule add in subdirectory' '
216 + echo "refs/heads/master" >expect &&
217 + >empty &&
218 +
219 + mkdir addtest/sub &&
220 + (
221 + cd addtest/sub &&
222 + git submodule add "$submodurl" ../realsubmod3 &&
223 + git submodule init
224 + ) &&
225 +
226 + rm -f heads head untracked &&
227 + inspect addtest/realsubmod3 ../.. &&
228 + test_cmp expect heads &&
229 + test_cmp expect head &&
230 + test_cmp empty untracked
231 +'
232 +
233 +test_expect_success 'submodule add in subdirectory with relative path should fail' '
234 + (
235 + cd addtest/sub &&
236 + test_must_fail git submodule add ../../ submod3 2>../../output.err
237 + ) &&
238 + test_i18ngrep toplevel output.err
239 +'
240 +
241 test_expect_success 'setup - add an example entry to .gitmodules' '
242 GIT_CONFIG=.gitmodules \
243 git config submodule.example.url git://example.com/init.git
@@ -319,6 +345,26 @@ test_expect_success 'status should be "up-to-date" after update' '
345 grep "^ $rev1" list
346 '
347
348 +test_expect_success 'status "up-to-date" from subdirectory' '
349 + mkdir -p sub &&
350 + (
351 + cd sub &&
352 + git submodule status >../list
353 + ) &&
354 + grep "^ $rev1" list &&
355 + grep "\\.\\./init" list
356 +'
357 +
358 +test_expect_success 'status "up-to-date" from subdirectory with path' '
359 + mkdir -p sub &&
360 + (
361 + cd sub &&
362 + git submodule status ../init >../list
363 + ) &&
364 + grep "^ $rev1" list &&
365 + grep "\\.\\./init" list
366 +'
367 +
368 test_expect_success 'status should be "modified" after submodule commit' '
369 (
370 cd init &&
@@ -399,6 +445,25 @@ test_expect_success 'update --init' '
445 git rev-parse --resolve-git-dir init/.git
446 '
447
448 +test_expect_success 'update --init from subdirectory' '
449 + mv init init2 &&
450 + git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
451 + git config --remove-section submodule.example &&
452 + test_must_fail git config submodule.example.url &&
453 +
454 + mkdir -p sub &&
455 + (
456 + cd sub &&
457 + git submodule update ../init >update.out &&
458 + cat update.out &&
459 + test_i18ngrep "not initialized" update.out &&
460 + test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
461 +
462 + git submodule update --init ../init
463 + ) &&
464 + git rev-parse --resolve-git-dir init/.git
465 +'
466 +
467 test_expect_success 'do not add files from a submodule' '
468
469 git reset --hard &&
@@ -772,6 +837,21 @@ test_expect_success 'submodule deinit should remove the whole submodule section
837 rmdir init
838 '
839
840 +test_expect_success 'submodule deinit from subdirectory' '
841 + git submodule update --init &&
842 + git config submodule.example.foo bar &&
843 + mkdir -p sub &&
844 + (
845 + cd sub &&
846 + git submodule deinit ../init >../output
847 + ) &&
848 + grep "\\.\\./init" output &&
849 + test -z "$(git config --get-regexp "submodule\.example\.")" &&
850 + test -n "$(git config --get-regexp "submodule\.example2\.")" &&
851 + test -f example2/.git &&
852 + rmdir init
853 +'
854 +
855 test_expect_success 'submodule deinit . deinits all initialized submodules' '
856 git submodule update --init &&
857 git config submodule.example.foo bar &&
t/t7401-submodule-summary.sh
+36
@@ -45,6 +45,42 @@ EOF
45 test_cmp expected actual
46 "
47
48 +test_expect_success 'added submodule (subdirectory)' "
49 + mkdir sub &&
50 + (
51 + cd sub &&
52 + git submodule summary >../actual
53 + ) &&
54 + cat >expected <<-EOF &&
55 +* ../sm1 0000000...$head1 (2):
56 + > Add foo2
57 +
58 +EOF
59 + test_cmp expected actual
60 +"
61 +
62 +test_expect_success 'added submodule (subdirectory only)' "
63 + (
64 + cd sub &&
65 + git submodule summary . >../actual
66 + ) &&
67 + >expected &&
68 + test_cmp expected actual
69 +"
70 +
71 +test_expect_success 'added submodule (subdirectory with explicit path)' "
72 + (
73 + cd sub &&
74 + git submodule summary ../sm1 >../actual
75 + ) &&
76 + cat >expected <<-EOF &&
77 +* ../sm1 0000000...$head1 (2):
78 + > Add foo2
79 +
80 +EOF
81 + test_cmp expected actual
82 +"
83 +
84 commit_file sm1 &&
85 head2=$(add_file sm1 foo3)
86
t/t7403-submodule-sync.sh
+72
@@ -61,6 +61,19 @@ test_expect_success 'change submodule' '
61 )
62 '
63
64 +reset_submodule_urls () {
65 + local root
66 + root=$(pwd) &&
67 + (
68 + cd super-clone/submodule &&
69 + git config remote.origin.url "$root/submodule"
70 + ) &&
71 + (
72 + cd super-clone/submodule/sub-submodule &&
73 + git config remote.origin.url "$root/submodule"
74 + )
75 +}
76 +
77 test_expect_success 'change submodule url' '
78 (
79 cd super &&
@@ -132,6 +145,65 @@ test_expect_success '"git submodule sync --recursive" should update all submodul
145 )
146 '
147
148 +test_expect_success 'reset submodule URLs' '
149 + reset_submodule_urls super-clone
150 +'
151 +
152 +test_expect_success '"git submodule sync" should update submodule URLs - subdirectory' '
153 + (
154 + cd super-clone &&
155 + git pull --no-recurse-submodules &&
156 + mkdir -p sub &&
157 + cd sub &&
158 + git submodule sync >../../output
159 + ) &&
160 + grep "\\.\\./submodule" output &&
161 + test -d "$(
162 + cd super-clone/submodule &&
163 + git config remote.origin.url
164 + )" &&
165 + test ! -d "$(
166 + cd super-clone/submodule/sub-submodule &&
167 + git config remote.origin.url
168 + )" &&
169 + (
170 + cd super-clone/submodule &&
171 + git checkout master &&
172 + git pull
173 + ) &&
174 + (
175 + cd super-clone &&
176 + test -d "$(git config submodule.submodule.url)"
177 + )
178 +'
179 +
180 +test_expect_success '"git submodule sync --recursive" should update all submodule URLs - subdirectory' '
181 + (
182 + cd super-clone &&
183 + (
184 + cd submodule &&
185 + git pull --no-recurse-submodules
186 + ) &&
187 + mkdir -p sub &&
188 + cd sub &&
189 + git submodule sync --recursive >../../output
190 + ) &&
191 + grep "\\.\\./submodule/sub-submodule" output &&
192 + test -d "$(
193 + cd super-clone/submodule &&
194 + git config remote.origin.url
195 + )" &&
196 + test -d "$(
197 + cd super-clone/submodule/sub-submodule &&
198 + git config remote.origin.url
199 + )" &&
200 + (
201 + cd super-clone/submodule/sub-submodule &&
202 + git checkout master &&
203 + git pull
204 + )
205 +'
206 +
207 test_expect_success '"git submodule sync" should update known submodule URLs' '
208 (
209 cd empty-clone &&
t/t7406-submodule-update.sh
+15
@@ -80,6 +80,21 @@ test_expect_success 'submodule update detaching the HEAD ' '
80 )
81 '
82
83 +test_expect_success 'submodule update from subdirectory' '
84 + (cd super/submodule &&
85 + git reset --hard HEAD~1
86 + ) &&
87 + mkdir super/sub &&
88 + (cd super/sub &&
89 + (cd ../submodule &&
90 + compare_head
91 + ) &&
92 + git submodule update ../submodule &&
93 + cd ../submodule &&
94 + ! compare_head
95 + )
96 +'
97 +
98 apos="'";
99 test_expect_success 'submodule update does not fetch already present commits' '
100 (cd submodule &&
t/t7407-submodule-foreach.sh
+16
@@ -80,6 +80,22 @@ test_expect_success 'test basic "submodule foreach" usage' '
80 test_i18ncmp expect actual
81 '
82
83 +cat >expect <<EOF
84 +Entering '../sub1'
85 +$pwd/clone-foo1-../sub1-$sub1sha1
86 +Entering '../sub3'
87 +$pwd/clone-foo3-../sub3-$sub3sha1
88 +EOF
89 +
90 +test_expect_success 'test "submodule foreach" from subdirectory' '
91 + mkdir clone/sub &&
92 + (
93 + cd clone/sub &&
94 + git submodule foreach "echo \$toplevel-\$name-\$sm_path-\$sha1" >../../actual
95 + ) &&
96 + test_i18ncmp expect actual
97 +'
98 +
99 test_expect_success 'setup nested submodules' '
100 git clone submodule nested1 &&
101 git clone submodule nested2 &&