submodule: prevent backslash expantion in submodule names

When attempting to add a submodule with backslashes in its name 'git submodule' fails in a funny way. We can see that some of the backslashes are expanded resulting in a bogus path: git -C main submodule add ../sub\\with\\backslash fatal: repository '/tmp/test/sub\witackslash' does not exist fatal: clone of '/tmp/test/sub\witackslash' into submodule path To solve this, convert calls to 'read' to 'read -r' in git-submodule.sh in order to prevent backslash expantion in submodule names. Reported-by: Joachim Durchholz <jo@durchholz.org> Signed-off-by: Brandon Williams <bmwill@google.com> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Apr 7, 2017 at 10:23 UTC cf9e55f49438d07dd554c5ade92f1c266363af36
2 files changed +21 -7
git-submodule.sh
+7 -7
@@ -332,7 +332,7 @@ cmd_foreach()
332 git submodule--helper list --prefix "$wt_prefix" ||
333 echo "#unmatched" $?
334 } |
335 - while read mode sha1 stage sm_path
335 + while read -r mode sha1 stage sm_path
336 do
337 die_if_unmatched "$mode" "$sha1"
338 if test -e "$sm_path"/.git
@@ -441,7 +441,7 @@ cmd_deinit()
441 git submodule--helper list --prefix "$wt_prefix" "$@" ||
442 echo "#unmatched" $?
443 } |
444 - while read mode sha1 stage sm_path
444 + while read -r mode sha1 stage sm_path
445 do
446 die_if_unmatched "$mode" "$sha1"
447 name=$(git submodule--helper name "$sm_path") || exit
@@ -605,7 +605,7 @@ cmd_update()
605 "$@" || echo "#unmatched" $?
606 } | {
607 err=
608 - while read mode sha1 stage just_cloned sm_path
608 + while read -r mode sha1 stage just_cloned sm_path
609 do
610 die_if_unmatched "$mode" "$sha1"
611
@@ -847,7 +847,7 @@ cmd_summary() {
847 # Get modified modules cared by user
848 modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
849 sane_egrep '^:([0-7]* )?160000' |
850 - while read mod_src mod_dst sha1_src sha1_dst status sm_path
850 + while read -r mod_src mod_dst sha1_src sha1_dst status sm_path
851 do
852 # Always show modules deleted or type-changed (blob<->module)
853 if test "$status" = D || test "$status" = T
@@ -873,7 +873,7 @@ cmd_summary() {
873 git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
874 sane_egrep '^:([0-7]* )?160000' |
875 cut -c2- |
876 - while read mod_src mod_dst sha1_src sha1_dst status name
876 + while read -r mod_src mod_dst sha1_src sha1_dst status name
877 do
878 if test -z "$cached" &&
879 test $sha1_dst = 0000000000000000000000000000000000000000
@@ -1020,7 +1020,7 @@ cmd_status()
1020 git submodule--helper list --prefix "$wt_prefix" "$@" ||
1021 echo "#unmatched" $?
1022 } |
1023 - while read mode sha1 stage sm_path
1023 + while read -r mode sha1 stage sm_path
1024 do
1025 die_if_unmatched "$mode" "$sha1"
1026 name=$(git submodule--helper name "$sm_path") || exit
@@ -1100,7 +1100,7 @@ cmd_sync()
1100 git submodule--helper list --prefix "$wt_prefix" "$@" ||
1101 echo "#unmatched" $?
1102 } |
1103 - while read mode sha1 stage sm_path
1103 + while read -r mode sha1 stage sm_path
1104 do
1105 die_if_unmatched "$mode" "$sha1"
1106
t/t7400-submodule-basic.sh
+14
@@ -273,6 +273,20 @@ test_expect_success 'submodule add with ./, /.. and // in path' '
273 test_cmp empty untracked
274 '
275
276 +test_expect_success 'submodule add with \\ in path' '
277 + test_when_finished "rm -rf parent sub\\with\\backslash" &&
278 +
279 + # Initialize a repo with a backslash in its name
280 + git init sub\\with\\backslash &&
281 + touch sub\\with\\backslash/empty.file &&
282 + git -C sub\\with\\backslash add empty.file &&
283 + git -C sub\\with\\backslash commit -m "Added empty.file" &&
284 +
285 + # Add that repository as a submodule
286 + git init parent &&
287 + git -C parent submodule add ../sub\\with\\backslash
288 +'
289 +
290 test_expect_success 'submodule add in subdirectory' '
291 echo "refs/heads/master" >expect &&
292 >empty &&