From: Junio C Hamano Date: Thu, 5 Mar 2015 21:13:09 +0000 (-0800) Subject: Merge branch 'ps/submodule-sanitize-path-upon-add' into maint X-Git-Tag: v2.3.2~11 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/3630be2749819b79de917a77c6627e3f84c00a11?ds=inline;hp=-c Merge branch 'ps/submodule-sanitize-path-upon-add' into maint "git submodule add" failed to squash "path/to/././submodule" to "path/to/submodule". * ps/submodule-sanitize-path-upon-add: git-submodule.sh: fix '/././' path normalization --- 3630be2749819b79de917a77c6627e3f84c00a11 diff --combined git-submodule.sh index 9245abfd42,6bf85f5afe..36797c3c00 --- a/git-submodule.sh +++ b/git-submodule.sh @@@ -9,7 -9,7 +9,7 @@@ USAGE="[--quiet] add [-b ] [-f| or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] or: $dashless [--quiet] deinit [-f|--force] [--] ... - or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] + or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference ] [--recursive] [--] [...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] or: $dashless [--quiet] sync [--recursive] [--] [...]" @@@ -156,7 -156,7 +156,7 @@@ module_list( git ls-files -z --error-unmatch --stage -- "$@" || echo "unmatched pathspec exists" ) | - perl -e ' + @@PERL@@ -e ' my %unmerged = (); my ($null_sha1) = ("0" x 40); my @out = (); @@@ -235,18 -235,12 +235,18 @@@ module_name( sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' ) test -z "$name" && die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")" - echo "$name" + printf '%s\n' "$name" } # # Clone a submodule # +# $1 = submodule path +# $2 = submodule name +# $3 = URL to clone +# $4 = reference repository to reuse (empty for independent) +# $5 = depth argument for shallow clones (empty for deep) +# # Prior to calling, cmd_update checks that a possibly existing # path is not a git repository. # Likewise, cmd_add checks that path does not exist at all, @@@ -291,6 -285,9 +291,6 @@@ module_clone( # resolve any symlinks that might be present in $PWD a=$(cd_to_toplevel && cd "$gitdir" && pwd)/ b=$(cd_to_toplevel && cd "$sm_path" && pwd)/ - # normalize Windows-style absolute paths to POSIX-style absolute paths - case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac - case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac # Remove all common leading directories after a sanity check if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")" @@@ -305,10 -302,10 +305,10 @@@ b=${b%/} # Turn each leading "*/" component into "../" - rel=$(echo $b | sed -e 's|[^/][^/]*|..|g') - echo "gitdir: $rel/$a" >"$sm_path/.git" + rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g') + printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git" - rel=$(echo $a | sed -e 's|[^/][^/]*|..|g') + rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g') (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b") } @@@ -389,11 -386,11 +389,11 @@@ cmd_add( sm_path=$2 if test -z "$sm_path"; then - sm_path=$(echo "$repo" | + sm_path=$(printf '%s\n' "$repo" | sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g') fi - if test -z "$repo" -o -z "$sm_path"; then + if test -z "$repo" || test -z "$sm_path"; then usage fi @@@ -423,7 -420,7 +423,7 @@@ sed -e ' s|//*|/|g s|^\(\./\)*|| - s|/\./|/|g + s|/\(\./\)*|/|g :start s|\([^/]*\)/\.\./|| tstart @@@ -450,7 -447,7 +450,7 @@@ Use -f if you really want to add it." > # perhaps the path exists and is already a git repo, else clone it if test -e "$sm_path" then - if test -d "$sm_path"/.git -o -f "$sm_path"/.git + if test -d "$sm_path"/.git || test -f "$sm_path"/.git then eval_gettextln "Adding existing repo at '\$sm_path' to the index" else @@@ -548,12 -545,7 +548,12 @@@ cmd_foreach( sm_path=$(relative_path "$sm_path") && # we make $path available to scripts ... path=$sm_path && - eval "$@" && + if test $# -eq 1 + then + eval "$1" + else + "$@" + fi && if test -n "$recursive" then cmd_foreach "--recursive" "$@" @@@ -625,7 -617,7 +625,7 @@@ cmd_init( test -z "$(git config submodule."$name".update)" then case "$upd" in - rebase | merge | none) + checkout | rebase | merge | none) ;; # known modes of updating *) echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'" @@@ -724,6 -716,7 +724,6 @@@ cmd_deinit( cmd_update() { # parse $args after "submodule ... update". - orig_flags= while test $# -ne 0 do case "$1" in @@@ -748,6 -741,7 +748,6 @@@ --reference) case "$2" in '') usage ;; esac reference="--reference=$2" - orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")" shift ;; --reference=*) @@@ -781,6 -775,7 +781,6 @@@ break ;; esac - orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")" shift done @@@ -808,10 -803,6 +808,10 @@@ update_module=$update else update_module=$(git config submodule."$name".update) + if test -z "$update_module" + then + update_module="checkout" + fi fi displaypath=$(relative_path "$prefix$sm_path") @@@ -832,7 -823,7 +832,7 @@@ Maybe you want to use 'update --init'?" continue fi - if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git + if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git then module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit cloned_modules="$cloned_modules;$name" @@@ -857,11 -848,11 +857,11 @@@ die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")" fi - if test "$subsha1" != "$sha1" -o -n "$force" + if test "$subsha1" != "$sha1" || test -n "$force" then subforce=$force # If we don't already have a -f flag and the submodule has never been checked out - if test -z "$subsha1" -a -z "$force" + if test -z "$subsha1" && test -z "$force" then subforce="-f" fi @@@ -880,16 -871,11 +880,16 @@@ case ";$cloned_modules;" in *";$name;"*) # then there is no local change to integrate - update_module= ;; + update_module=checkout ;; esac must_die_on_failure= case "$update_module" in + checkout) + command="git checkout $subforce -q" + die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")" + say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")" + ;; rebase) command="git rebase" die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")" @@@ -909,7 -895,10 +909,7 @@@ must_die_on_failure=yes ;; *) - command="git checkout $subforce -q" - die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")" - say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")" - ;; + die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")" esac if (clear_local_git_env; cd "$sm_path" && $command "$sha1") @@@ -930,7 -919,7 +930,7 @@@ prefix="$prefix$sm_path/" clear_local_git_env cd "$sm_path" && - eval cmd_update "$orig_flags" + eval cmd_update ) res=$? if test $res -gt 0 @@@ -1031,7 -1020,7 +1031,7 @@@ cmd_summary() then head=$rev test $# = 0 || shift - elif test -z "$1" -o "$1" = "HEAD" + elif test -z "$1" || test "$1" = "HEAD" then # before the first commit: compare with an empty tree head=$(git hash-object -w -t tree --stdin module) - test $status = D -o $status = T && echo "$sm_path" && continue + if test "$status" = D || test "$status" = T + then + printf '%s\n' "$sm_path" + continue + fi # Respect the ignore setting for --for-status. if test -n "$for_status" then name=$(module_name "$sm_path") ignore_config=$(get_submodule_config "$name" ignore none) - test $status != A -a $ignore_config = all && continue + test $status != A && test $ignore_config = all && continue fi # Also show added or modified modules which are checked out GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 && - echo "$sm_path" + printf '%s\n' "$sm_path" done ) @@@ -1126,7 -1111,7 +1126,7 @@@ *) errmsg= total_commits=$( - if test $mod_src = 160000 -a $mod_dst = 160000 + if test $mod_src = 160000 && test $mod_dst = 160000 then range="$sha1_src...$sha1_dst" elif test $mod_src = 160000 @@@ -1163,7 -1148,7 +1163,7 @@@ # i.e. deleted or changed to blob test $mod_dst = 160000 && echo "$errmsg" else - if test $mod_src = 160000 -a $mod_dst = 160000 + if test $mod_src = 160000 && test $mod_dst = 160000 then limit= test $summary_limit -gt 0 && limit="-$summary_limit" @@@ -1234,11 -1219,7 +1234,11 @@@ cmd_status( say "U$sha1 $displaypath" continue fi - if test -z "$url" || ! test -d "$sm_path"/.git -o -f "$sm_path"/.git + if test -z "$url" || + { + ! test -d "$sm_path"/.git && + ! test -f "$sm_path"/.git + } then say "-$sha1 $displaypath" continue; @@@ -1311,7 -1292,7 +1311,7 @@@ cmd_sync( ./*|../*) # rewrite foo/bar as ../.. to find path from # submodule work tree to superproject work tree - up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" && + up_path="$(printf '%s\n' "$sm_path" | sed "s/[^/][^/]*/../g")" && # guarantee a trailing / up_path=${up_path%/}/ && # path from submodule work tree to submodule origin repo @@@ -1407,7 -1388,7 +1407,7 @@@ the fi # "--cached" is accepted only by "status" and "summary" -if test -n "$cached" && test "$command" != status -a "$command" != summary +if test -n "$cached" && test "$command" != status && test "$command" != summary then usage fi diff --combined t/t7400-submodule-basic.sh index 7c88245031,4004d12668..5811a982f4 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@@ -170,6 -170,23 +170,23 @@@ test_expect_success 'submodule add wit test_cmp expect head && test_cmp empty untracked ' + + test_expect_success 'submodule add with /././ in path' ' + echo "refs/heads/master" >expect && + >empty && + + ( + cd addtest && + git submodule add "$submodurl" dotslashdotsubmod/././frotz/./ && + git submodule init + ) && + + rm -f heads head untracked && + inspect addtest/dotslashdotsubmod/frotz ../../.. && + test_cmp expect heads && + test_cmp expect head && + test_cmp empty untracked + ' test_expect_success 'submodule add with // in path' ' echo "refs/heads/master" >expect && @@@ -249,7 -266,8 +266,7 @@@ test_expect_success 'submodule add in s ' test_expect_success 'setup - add an example entry to .gitmodules' ' - GIT_CONFIG=.gitmodules \ - git config submodule.example.url git://example.com/init.git + git config --file=.gitmodules submodule.example.url git://example.com/init.git ' test_expect_success 'status should fail for unmapped paths' ' @@@ -263,7 -281,7 +280,7 @@@ test_expect_success 'setup - map path i path = init EOF - GIT_CONFIG=.gitmodules git config submodule.example.path init && + git config --file=.gitmodules submodule.example.path init && test_cmp expect .gitmodules '