]> git.ipfire.org Git - thirdparty/git.git/blobdiff - git-submodule.sh
reftable: fix OOB stack write in print functions
[thirdparty/git.git] / git-submodule.sh
index dbd2ec205037e062b6fb4ae52205bbf84e023001..652861aa66a400940c24ea8405177f372009eafe 100755 (executable)
@@ -63,11 +63,6 @@ isnumber()
        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
 }
 
-# Given a full hex object ID, is this the zero OID?
-is_zero_oid () {
-       echo "$1" | sane_egrep '^0+$' >/dev/null 2>&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.
@@ -145,130 +140,12 @@ cmd_add()
                shift
        done
 
-       if ! git submodule--helper config --check-writeable >/dev/null 2>&1
-       then
-                die "fatal: $(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
-       fi
-
-       if test -n "$reference_path"
+       if test -z "$1"
        then
-               is_absolute_path "$reference_path" ||
-               reference_path="$wt_prefix$reference_path"
-
-               reference="--reference=$reference_path"
-       fi
-
-       repo=$1
-       sm_path=$2
-
-       if test -z "$sm_path"; then
-               sm_path=$(printf '%s\n' "$repo" |
-                       sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-       fi
-
-       if test -z "$repo" || test -z "$sm_path"; then
                usage
        fi
 
-       is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
-
-       # assure repo is absolute or relative to parent
-       case "$repo" in
-       ./*|../*)
-               test -z "$wt_prefix" ||
-               die "fatal: $(gettext "Relative path can only be used from the toplevel of the working tree")"
-
-               # dereference source url relative to parent's url
-               realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
-               ;;
-       *:*|/*)
-               # absolute url
-               realrepo=$repo
-               ;;
-       *)
-               die "fatal: $(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
-       ;;
-       esac
-
-       # normalize path:
-       # multiple //; leading ./; /./; /../; trailing /
-       sm_path=$(printf '%s/\n' "$sm_path" |
-               sed -e '
-                       s|//*|/|g
-                       s|^\(\./\)*||
-                       s|/\(\./\)*|/|g
-                       :start
-                       s|\([^/]*\)/\.\./||
-                       tstart
-                       s|/*$||
-               ')
-       if test -z "$force"
-       then
-               git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
-               die "fatal: $(eval_gettext "'\$sm_path' already exists in the index")"
-       else
-               git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
-               die "fatal: $(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
-       fi
-
-       if test -d "$sm_path" &&
-               test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
-       then
-           git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
-           die "fatal: $(eval_gettext "'\$sm_path' does not have a commit checked out")"
-       fi
-
-       if test -z "$force"
-       then
-           dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null)
-           res=$?
-           if test $res -ne 0
-           then
-                echo >&2 "$dryerr"
-                exit $res
-           fi
-       fi
-
-       if test -n "$custom_name"
-       then
-               sm_name="$custom_name"
-       else
-               sm_name="$sm_path"
-       fi
-
-       if ! git submodule--helper check-name "$sm_name"
-       then
-               die "fatal: $(eval_gettext "'$sm_name' is not a valid submodule name")"
-       fi
-
-       git submodule--helper add-clone ${GIT_QUIET:+--quiet} ${force:+"--force"} ${progress:+"--progress"} ${branch:+--branch "$branch"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
-       git config submodule."$sm_name".url "$realrepo"
-
-       git add --no-warn-embedded-repo $force "$sm_path" ||
-       die "fatal: $(eval_gettext "Failed to add submodule '\$sm_path'")"
-
-       git submodule--helper config submodule."$sm_name".path "$sm_path" &&
-       git submodule--helper config submodule."$sm_name".url "$repo" &&
-       if test -n "$branch"
-       then
-               git submodule--helper config submodule."$sm_name".branch "$branch"
-       fi &&
-       git add --force .gitmodules ||
-       die "fatal: $(eval_gettext "Failed to register submodule '\$sm_path'")"
-
-       # NEEDSWORK: In a multi-working-tree world, this needs to be
-       # set in the per-worktree config.
-       if git config --get submodule.active >/dev/null
-       then
-               # If the submodule being adding isn't already covered by the
-               # current configured pathspec, set the submodule's active flag
-               if ! git submodule--helper is-active "$sm_path"
-               then
-                       git config submodule."$sm_name".active "true"
-               fi
-       else
-               git config submodule."$sm_name".active "true"
-       fi
+       git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
 }
 
 #
@@ -369,13 +246,6 @@ cmd_deinit()
        git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
 }
 
-is_tip_reachable () (
-       sanitize_submodule_env &&
-       cd "$1" &&
-       rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) &&
-       test -z "$rev"
-)
-
 # usage: fetch_in_submodule <module_path> [<depth>] [<sha1>]
 # Because arguments are positional, use an empty string to omit <depth>
 # but include <sha1>.
@@ -519,14 +389,13 @@ cmd_update()
 
                git submodule--helper ensure-core-worktree "$sm_path" || exit 1
 
-               update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update)
-
                displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
 
                if test $just_cloned -eq 1
                then
                        subsha1=
                else
+                       just_cloned=
                        subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
                        die "fatal: $(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
@@ -547,70 +416,38 @@ cmd_update()
                        die "fatal: $(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
                fi
 
-               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" && test -z "$force"
-                       then
-                               subforce="-f"
-                       fi
-
-                       if test -z "$nofetch"
-                       then
-                               # Run fetch only if $sha1 isn't present or it
-                               # is not reachable from a ref.
-                               is_tip_reachable "$sm_path" "$sha1" ||
-                               fetch_in_submodule "$sm_path" $depth ||
-                               say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'; trying to directly fetch \$sha1:")"
-
-                               # Now we tried the usual fetch, but $sha1 may
-                               # not be reachable from any of the refs
-                               is_tip_reachable "$sm_path" "$sha1" ||
-                               fetch_in_submodule "$sm_path" "$depth" "$sha1" ||
-                               die "fatal: $(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")"
-                       fi
-
-                       must_die_on_failure=
-                       case "$update_module" in
-                       checkout)
-                               command="git checkout $subforce -q"
-                               die_msg="fatal: $(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
-                               say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
-                               ;;
-                       rebase)
-                               command="git rebase ${GIT_QUIET:+--quiet}"
-                               die_msg="fatal: $(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
-                               say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
-                               must_die_on_failure=yes
-                               ;;
-                       merge)
-                               command="git merge ${GIT_QUIET:+--quiet}"
-                               die_msg="fatal: $(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
-                               say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
-                               must_die_on_failure=yes
-                               ;;
-                       !*)
-                               command="${update_module#!}"
-                               die_msg="fatal: $(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 "fatal: $(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")"
-                       esac
-
-                       if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
-                       then
-                               say "$say_msg"
-                       elif test -n "$must_die_on_failure"
-                       then
-                               die_with_status 2 "$die_msg"
-                       else
-                               err="${err};$die_msg"
-                               continue
-                       fi
-               fi
+               out=$(git submodule--helper run-update-procedure \
+                         ${wt_prefix:+--prefix "$wt_prefix"} \
+                         ${GIT_QUIET:+--quiet} \
+                         ${force:+--force} \
+                         ${just_cloned:+--just-cloned} \
+                         ${nofetch:+--no-fetch} \
+                         ${depth:+"$depth"} \
+                         ${update:+--update "$update"} \
+                         ${prefix:+--recursive-prefix "$prefix"} \
+                         ${sha1:+--oid "$sha1"} \
+                         ${subsha1:+--suboid "$subsha1"} \
+                         "--" \
+                         "$sm_path")
+
+               # exit codes for run-update-procedure:
+               # 0: update was successful, say command output
+               # 1: update procedure failed, but should not die
+               # 2 or 128: subcommand died during execution
+               # 3: no update procedure was run
+               res="$?"
+               case $res in
+               0)
+                       say "$out"
+                       ;;
+               1)
+                       err="${err};fatal: $out"
+                       continue
+                       ;;
+               2|128)
+                       die_with_status $res "fatal: $out"
+                       ;;
+               esac
 
                if test -n "$recursive"
                then