]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'sb/submodule-path-misc-bugs'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Apr 2016 22:17:16 +0000 (15:17 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Apr 2016 22:17:16 +0000 (15:17 -0700)
"git submodule" reports the paths of submodules the command
recurses into, but this was incorrect when the command was not run
from the root level of the superproject.

* sb/submodule-path-misc-bugs:
  t7407: make expectation as clear as possible
  submodule update: test recursive path reporting from subdirectory
  submodule update: align reporting path for custom command execution
  submodule status: correct path handling in recursive submodules
  submodule update --init: correct path handling in recursive submodules
  submodule foreach: correct path display in recursive submodules

1  2 
git-submodule.sh
t/t7406-submodule-update.sh

diff --combined git-submodule.sh
index cd749f473c5fc8bdd16018c5b735a215176230bb,753a90d3071d1917495ca725fe15a944f84b6f60..2a84d7e66a0e6c2bbd0bee1c3e796e4580feaea9
@@@ -192,16 -192,6 +192,16 @@@ isnumber(
        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
  }
  
 +# Sanitize the local git environment for use within a submodule. We
 +# can't simply use clear_local_git_env since we want to preserve some
 +# of the settings from GIT_CONFIG_PARAMETERS.
 +sanitize_submodule_env()
 +{
 +      sanitized_config=$(git submodule--helper sanitize-config)
 +      clear_local_git_env
 +      GIT_CONFIG_PARAMETERS=$sanitized_config
 +}
 +
  #
  # Add a new submodule to the working tree, .gitmodules and the index
  #
@@@ -357,9 -347,9 +357,9 @@@ Use -f if you really want to add it." >
                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
                        fi
                fi
 -              git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
 +              git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit
                (
 -                      clear_local_git_env
 +                      sanitize_submodule_env
                        cd "$sm_path" &&
                        # ash fails to wordsplit ${branch:+-b "$branch"...}
                        case "$branch" in
@@@ -423,12 -413,12 +423,12 @@@ cmd_foreach(
                die_if_unmatched "$mode"
                if test -e "$sm_path"/.git
                then
-                       displaypath=$(relative_path "$sm_path")
-                       say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
+                       displaypath=$(relative_path "$prefix$sm_path")
+                       say "$(eval_gettext "Entering '\$displaypath'")"
                        name=$(git submodule--helper name "$sm_path")
                        (
                                prefix="$prefix$sm_path/"
 -                              clear_local_git_env
 +                              sanitize_submodule_env
                                cd "$sm_path" &&
                                sm_path=$(relative_path "$sm_path") &&
                                # we make $path available to scripts ...
                                        cmd_foreach "--recursive" "$@"
                                fi
                        ) <&3 3<&- ||
-                       die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
+                       die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")"
                fi
        done
  }
@@@ -483,7 -473,7 +483,7 @@@ cmd_init(
                die_if_unmatched "$mode"
                name=$(git submodule--helper name "$sm_path") || exit
  
-               displaypath=$(relative_path "$sm_path")
+               displaypath=$(relative_path "$prefix$sm_path")
  
                # Copy url setting when it is not set yet
                if test -z "$(git config "submodule.$name.url")"
@@@ -602,14 -592,14 +602,14 @@@ cmd_deinit(
  }
  
  is_tip_reachable () (
 -      clear_local_git_env
 +      sanitize_submodule_env &&
        cd "$1" &&
        rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) &&
        test -z "$rev"
  )
  
  fetch_in_submodule () (
 -      clear_local_git_env
 +      sanitize_submodule_env &&
        cd "$1" &&
        case "$2" in
        '')
@@@ -673,14 -663,6 +673,14 @@@ cmd_update(
                --depth=*)
                        depth=$1
                        ;;
 +              -j|--jobs)
 +                      case "$2" in '') usage ;; esac
 +                      jobs="--jobs=$2"
 +                      shift
 +                      ;;
 +              --jobs=*)
 +                      jobs=$1
 +                      ;;
                --)
                        shift
                        break
                cmd_init "--" "$@" || return
        fi
  
 -      cloned_modules=
 -      git submodule--helper list --prefix "$wt_prefix" "$@" | {
 +      {
 +      git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
 +              ${wt_prefix:+--prefix "$wt_prefix"} \
 +              ${prefix:+--recursive-prefix "$prefix"} \
 +              ${update:+--update "$update"} \
 +              ${reference:+--reference "$reference"} \
 +              ${depth:+--depth "$depth"} \
 +              ${jobs:+$jobs} \
 +              "$@" || echo "#unmatched"
 +      } | {
        err=
 -      while read mode sha1 stage sm_path
 +      while read mode sha1 stage just_cloned sm_path
        do
                die_if_unmatched "$mode"
 -              if test "$stage" = U
 -              then
 -                      echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 -                      continue
 -              fi
 +
                name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                branch=$(get_submodule_config "$name" branch master)
  
                displaypath=$(relative_path "$prefix$sm_path")
  
 -              if test "$update_module" = "none"
 -              then
 -                      echo "Skipping submodule '$displaypath'"
 -                      continue
 -              fi
 -
 -              if test -z "$url"
 +              if test $just_cloned -eq 1
                then
 -                      # Only mention uninitialized submodules when its
 -                      # path have been specified
 -                      test "$#" != "0" &&
 -                      say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 -Maybe you want to use 'update --init'?")"
 -                      continue
 -              fi
 -
 -              if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
 -              then
 -                      git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
 -                      cloned_modules="$cloned_modules;$name"
                        subsha1=
 +                      update_module=checkout
                else
 -                      subsha1=$(clear_local_git_env; cd "$sm_path" &&
 +                      subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
                        die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
                fi
                        if test -z "$nofetch"
                        then
                                # Fetch remote before determining tracking $sha1
 -                              (clear_local_git_env; cd "$sm_path" && git-fetch) ||
 +                              (sanitize_submodule_env; cd "$sm_path" && git-fetch) ||
                                die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
                        fi
 -                      remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
 -                      sha1=$(clear_local_git_env; cd "$sm_path" &&
 +                      remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
 +                      sha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify "${remote_name}/${branch}") ||
                        die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
                fi
                                die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain $sha1. Direct fetching of that commit failed.")"
                        fi
  
 -                      # Is this something we just cloned?
 -                      case ";$cloned_modules;" in
 -                      *";$name;"*)
 -                              # then there is no local change to integrate
 -                              update_module=checkout ;;
 -                      esac
 -
                        must_die_on_failure=
                        case "$update_module" in
                        checkout)
                                ;;
                        !*)
                                command="${update_module#!}"
-                               die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
+                               die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")"
+                               say_msg="$(eval_gettext "Submodule path '\$displaypath': '\$command \$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        *)
                                die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
                        esac
  
 -                      if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
 +                      if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
                        then
                                say "$say_msg"
                        elif test -n "$must_die_on_failure"
                then
                        (
                                prefix="$prefix$sm_path/"
 -                              clear_local_git_env
 +                              sanitize_submodule_env
                                cd "$sm_path" &&
                                eval cmd_update
                        )
  
  set_name_rev () {
        revname=$( (
 -              clear_local_git_env
 +              sanitize_submodule_env
                cd "$1" && {
                        git describe "$2" 2>/dev/null ||
                        git describe --tags "$2" 2>/dev/null ||
@@@ -1146,7 -1148,7 +1146,7 @@@ cmd_status(
                else
                        if test -z "$cached"
                        then
 -                              sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
 +                              sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD)
                        fi
                        set_name_rev "$sm_path" "$sha1"
                        say "+$sha1 $displaypath$revname"
                then
                        (
                                prefix="$displaypath/"
 -                              clear_local_git_env
 +                              sanitize_submodule_env
+                               wt_prefix=
                                cd "$sm_path" &&
                                eval cmd_status
                        ) ||
@@@ -1230,7 -1233,7 +1231,7 @@@ cmd_sync(
                        if test -e "$sm_path"/.git
                        then
                        (
 -                              clear_local_git_env
 +                              sanitize_submodule_env
                                cd "$sm_path"
                                remote=$(get_default_remote)
                                git config remote."$remote".url "$sub_origin_url"
index 0791df75aca9e318077b95f2892c3a728eefc2df,e5af4b497646944d0c116f68de5b05bd6dfd7445..fd741f506f4192e56348fcced49b2deabe59b9e7
@@@ -63,6 -63,10 +63,10 @@@ test_expect_success 'setup a submodule 
         git submodule add ../none none &&
         test_tick &&
         git commit -m "none"
+       ) &&
+       git clone . recursivesuper &&
+       ( cd recursivesuper
+        git submodule add ../super super
        )
  '
  
@@@ -95,6 -99,35 +99,35 @@@ test_expect_success 'submodule update f
        )
  '
  
+ supersha1=$(git -C super rev-parse HEAD)
+ mergingsha1=$(git -C super/merging rev-parse HEAD)
+ nonesha1=$(git -C super/none rev-parse HEAD)
+ rebasingsha1=$(git -C super/rebasing rev-parse HEAD)
+ submodulesha1=$(git -C super/submodule rev-parse HEAD)
+ pwd=$(pwd)
+ cat <<EOF >expect
+ Submodule path '../super': checked out '$supersha1'
+ Submodule 'merging' ($pwd/merging) registered for path '../super/merging'
+ Submodule 'none' ($pwd/none) registered for path '../super/none'
+ Submodule 'rebasing' ($pwd/rebasing) registered for path '../super/rebasing'
+ Submodule 'submodule' ($pwd/submodule) registered for path '../super/submodule'
+ Submodule path '../super/merging': checked out '$mergingsha1'
+ Submodule path '../super/none': checked out '$nonesha1'
+ Submodule path '../super/rebasing': checked out '$rebasingsha1'
+ Submodule path '../super/submodule': checked out '$submodulesha1'
+ EOF
+ test_expect_success 'submodule update --init --recursive from subdirectory' '
+       git -C recursivesuper/super reset --hard HEAD^ &&
+       (cd recursivesuper &&
+        mkdir tmp &&
+        cd tmp &&
+        git submodule update --init --recursive ../super >../../actual
+       ) &&
+       test_cmp expect actual
+ '
  apos="'";
  test_expect_success 'submodule update does not fetch already present commits' '
        (cd submodule &&
@@@ -311,16 -344,59 +344,59 @@@ test_expect_success 'submodule update 
        )
  '
  
+ cat << EOF >expect
+ Execution of 'false $submodulesha1' failed in submodule path 'submodule'
+ EOF
  test_expect_success 'submodule update - command in .git/config catches failure' '
        (cd super &&
         git config submodule.submodule.update "!false"
        ) &&
        (cd super/submodule &&
-         git reset --hard HEAD^
+         git reset --hard $submodulesha1^
        ) &&
        (cd super &&
-        test_must_fail git submodule update submodule
-       )
+        test_must_fail git submodule update submodule 2>../actual
+       ) &&
+       test_cmp actual expect
+ '
+ cat << EOF >expect
+ Execution of 'false $submodulesha1' failed in submodule path '../submodule'
+ EOF
+ test_expect_success 'submodule update - command in .git/config catches failure -- subdirectory' '
+       (cd super &&
+        git config submodule.submodule.update "!false"
+       ) &&
+       (cd super/submodule &&
+         git reset --hard $submodulesha1^
+       ) &&
+       (cd super &&
+        mkdir tmp && cd tmp &&
+        test_must_fail git submodule update ../submodule 2>../../actual
+       ) &&
+       test_cmp actual expect
+ '
+ cat << EOF >expect
+ Execution of 'false $submodulesha1' failed in submodule path '../super/submodule'
+ Failed to recurse into submodule path '../super'
+ EOF
+ test_expect_success 'recursive submodule update - command in .git/config catches failure -- subdirectory' '
+       (cd recursivesuper &&
+        git submodule update --remote super &&
+        git add super &&
+        git commit -m "update to latest to have more than one commit in submodules"
+       ) &&
+       git -C recursivesuper/super config submodule.submodule.update "!false" &&
+       git -C recursivesuper/super/submodule reset --hard $submodulesha1^ &&
+       (cd recursivesuper &&
+        mkdir -p tmp && cd tmp &&
+        test_must_fail git submodule update --recursive ../super 2>../../actual
+       ) &&
+       test_cmp actual expect
  '
  
  test_expect_success 'submodule init does not copy command into .git/config' '
@@@ -774,31 -850,4 +850,31 @@@ test_expect_success 'submodule update -
         test_i18ngrep "Submodule path .deeper/submodule/subsubmodule.: checked out" actual
        )
  '
 +
 +test_expect_success 'submodule update can be run in parallel' '
 +      (cd super2 &&
 +       GIT_TRACE=$(pwd)/trace.out git submodule update --jobs 7 &&
 +       grep "7 tasks" trace.out &&
 +       git config submodule.fetchJobs 8 &&
 +       GIT_TRACE=$(pwd)/trace.out git submodule update &&
 +       grep "8 tasks" trace.out &&
 +       GIT_TRACE=$(pwd)/trace.out git submodule update --jobs 9 &&
 +       grep "9 tasks" trace.out
 +      )
 +'
 +
 +test_expect_success 'git clone passes the parallel jobs config on to submodules' '
 +      test_when_finished "rm -rf super4" &&
 +      GIT_TRACE=$(pwd)/trace.out git clone --recurse-submodules --jobs 7 . super4 &&
 +      grep "7 tasks" trace.out &&
 +      rm -rf super4 &&
 +      git config --global submodule.fetchJobs 8 &&
 +      GIT_TRACE=$(pwd)/trace.out git clone --recurse-submodules . super4 &&
 +      grep "8 tasks" trace.out &&
 +      rm -rf super4 &&
 +      GIT_TRACE=$(pwd)/trace.out git clone --recurse-submodules --jobs 9 . super4 &&
 +      grep "9 tasks" trace.out &&
 +      rm -rf super4
 +'
 +
  test_done