pretty: allow showing specific trailers
[gitweb.git] / git-submodule.sh
index f2e5bea715c3b184b98958c763f5ba9917a996ad..c09eb3e03d25510b2768d8f9c144cab2597fc000 100755 (executable)
@@ -42,6 +42,7 @@ prefix=
 custom_name=
 depth=
 progress=
+dissociate=
 
 die_if_unmatched ()
 {
@@ -81,6 +82,11 @@ 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.
@@ -117,6 +123,9 @@ cmd_add()
                -q|--quiet)
                        GIT_QUIET=1
                        ;;
+               --progress)
+                       progress=1
+                       ;;
                --reference)
                        case "$2" in '') usage ;; esac
                        reference_path=$2
@@ -125,6 +134,9 @@ cmd_add()
                --reference=*)
                        reference_path="${1#--reference=}"
                        ;;
+               --dissociate)
+                       dissociate=1
+                       ;;
                --name)
                        case "$2" in '') usage ;; esac
                        custom_name=$2
@@ -260,7 +272,7 @@ or you are unsure what this means choose another name with the '--name' option."
                                eval_gettextln "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:+"$reference"} ${depth:+"$depth"} || exit
+               git submodule--helper clone ${GIT_QUIET:+--quiet} ${progress:+"--progress"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
                (
                        sanitize_submodule_env
                        cd "$sm_path" &&
@@ -328,45 +340,7 @@ cmd_foreach()
                shift
        done
 
-       toplevel=$(pwd)
-
-       # dup stdin so that it can be restored when running the external
-       # command in the subshell (and a recursive call to this function)
-       exec 3<&0
-
-       {
-               git submodule--helper list --prefix "$wt_prefix" ||
-               echo "#unmatched" $?
-       } |
-       while read -r mode sha1 stage sm_path
-       do
-               die_if_unmatched "$mode" "$sha1"
-               if test -e "$sm_path"/.git
-               then
-                       displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
-                       say "$(eval_gettext "Entering '\$displaypath'")"
-                       name=$(git submodule--helper name "$sm_path")
-                       (
-                               prefix="$prefix$sm_path/"
-                               sanitize_submodule_env
-                               cd "$sm_path" &&
-                               sm_path=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") &&
-                               # we make $path available to scripts ...
-                               path=$sm_path &&
-                               if test $# -eq 1
-                               then
-                                       eval "$1"
-                               else
-                                       "$@"
-                               fi &&
-                               if test -n "$recursive"
-                               then
-                                       cmd_foreach "--recursive" "$@"
-                               fi
-                       ) <&3 3<&- ||
-                       die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")"
-               fi
-       done
+       git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} "$@"
 }
 
 #
@@ -433,60 +407,7 @@ cmd_deinit()
                shift
        done
 
-       if test -n "$deinit_all" && test "$#" -ne 0
-       then
-               echo >&2 "$(eval_gettext "pathspec and --all are incompatible")"
-               usage
-       fi
-       if test $# = 0 && test -z "$deinit_all"
-       then
-               die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")"
-       fi
-
-       {
-               git submodule--helper list --prefix "$wt_prefix" "$@" ||
-               echo "#unmatched" $?
-       } |
-       while read -r mode sha1 stage sm_path
-       do
-               die_if_unmatched "$mode" "$sha1"
-               name=$(git submodule--helper name "$sm_path") || exit
-
-               displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix")
-
-               # Remove the submodule work tree (unless the user already did it)
-               if test -d "$sm_path"
-               then
-                       # Protect submodules containing a .git directory
-                       if test -d "$sm_path/.git"
-                       then
-                               die "$(eval_gettext "\
-Submodule work tree '\$displaypath' contains a .git directory
-(use 'rm -rf' if you really want to remove it including all of its history)")"
-                       fi
-
-                       if test -z "$force"
-                       then
-                               git rm -qn "$sm_path" ||
-                               die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
-                       fi
-                       rm -rf "$sm_path" &&
-                       say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
-                       say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
-               fi
-
-               mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
-
-               # Remove the .git/config entries (unless the user already did it)
-               if test -n "$(git config --get-regexp submodule."$name\.")"
-               then
-                       # Remove the whole section so we have a clean state when
-                       # the user later decides to init this submodule again
-                       url=$(git config submodule."$name".url)
-                       git config --remove-section submodule."$name" 2>/dev/null &&
-                       say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
-               fi
-       done
+       git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} "$@"
 }
 
 is_tip_reachable () (
@@ -522,8 +443,11 @@ cmd_update()
                -q|--quiet)
                        GIT_QUIET=1
                        ;;
+               -v)
+                       GIT_QUIET=0
+                       ;;
                --progress)
-                       progress="--progress"
+                       progress=1
                        ;;
                -i|--init)
                        init=1
@@ -548,6 +472,9 @@ cmd_update()
                --reference=*)
                        reference="$1"
                        ;;
+               --dissociate)
+                       dissociate=1
+                       ;;
                -m|--merge)
                        update="merge"
                        ;;
@@ -600,42 +527,31 @@ cmd_update()
 
        {
        git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
-               ${progress:+"$progress"} \
+               ${progress:+"--progress"} \
                ${wt_prefix:+--prefix "$wt_prefix"} \
                ${prefix:+--recursive-prefix "$prefix"} \
                ${update:+--update "$update"} \
                ${reference:+"$reference"} \
+               ${dissociate:+"--dissociate"} \
                ${depth:+--depth "$depth"} \
-               ${recommend_shallow:+"$recommend_shallow"} \
-               ${jobs:+$jobs} \
+               $recommend_shallow \
+               $jobs \
                "$@" || echo "#unmatched" $?
        } | {
        err=
-       while read -r mode sha1 stage just_cloned sm_path
+       while read -r quickabort sha1 just_cloned sm_path
        do
-               die_if_unmatched "$mode" "$sha1"
+               die_if_unmatched "$quickabort" "$sha1"
 
-               name=$(git submodule--helper name "$sm_path") || exit
-               if ! test -z "$update"
-               then
-                       update_module=$update
-               else
-                       update_module=$(git config submodule."$name".update)
-                       if test -z "$update_module"
-                       then
-                               update_module="checkout"
-                       fi
-               fi
+               git submodule--helper ensure-core-worktree "$sm_path"
+
+               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=
-                       case "$update_module" in
-                       merge | rebase | none)
-                               update_module=checkout ;;
-                       esac
                else
                        subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
@@ -672,7 +588,7 @@ cmd_update()
                                # is not reachable from a ref.
                                is_tip_reachable "$sm_path" "$sha1" ||
                                fetch_in_submodule "$sm_path" $depth ||
-                               die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
+                               say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
 
                                # Now we tried the usual fetch, but $sha1 may
                                # not be reachable from any of the refs
@@ -707,7 +623,7 @@ cmd_update()
                                must_die_on_failure=yes
                                ;;
                        *)
-                               die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
+                               die "$(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")"
                        esac
 
                        if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
@@ -869,7 +785,7 @@ cmd_summary() {
        while read -r mod_src mod_dst sha1_src sha1_dst status name
        do
                if test -z "$cached" &&
-                       test $sha1_dst = 0000000000000000000000000000000000000000
+                       is_zero_oid $sha1_dst
                then
                        case "$mod_dst" in
                        160000)
@@ -1041,63 +957,8 @@ cmd_sync()
                        ;;
                esac
        done
-       cd_to_toplevel
-       {
-               git submodule--helper list --prefix "$wt_prefix" "$@" ||
-               echo "#unmatched" $?
-       } |
-       while read -r mode sha1 stage sm_path
-       do
-               die_if_unmatched "$mode" "$sha1"
 
-               # skip inactive submodules
-               if ! git submodule--helper is-active "$sm_path"
-               then
-                       continue
-               fi
-
-               name=$(git submodule--helper name "$sm_path")
-               url=$(git config -f .gitmodules --get submodule."$name".url)
-
-               # Possibly a url relative to parent
-               case "$url" in
-               ./*|../*)
-                       # rewrite foo/bar as ../.. to find path from
-                       # submodule work tree to superproject work tree
-                       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
-                       sub_origin_url=$(git submodule--helper resolve-relative-url "$url" "$up_path") &&
-                       # path from superproject work tree to submodule origin repo
-                       super_config_url=$(git submodule--helper resolve-relative-url "$url") || exit
-                       ;;
-               *)
-                       sub_origin_url="$url"
-                       super_config_url="$url"
-                       ;;
-               esac
-
-               displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
-               say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
-               git config submodule."$name".url "$super_config_url"
-
-               if test -e "$sm_path"/.git
-               then
-               (
-                       sanitize_submodule_env
-                       cd "$sm_path"
-                       remote=$(get_default_remote)
-                       git config remote."$remote".url "$sub_origin_url"
-
-                       if test -n "$recursive"
-                       then
-                               prefix="$prefix$sm_path/"
-                               eval cmd_sync
-                       fi
-               )
-               fi
-       done
+       git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} "$@"
 }
 
 cmd_absorbgitdirs()