builtin/help.c: add --guide option
[gitweb.git] / git-submodule.sh
index f2c53c9a02d84ae4ecd0f465388d26febfcae519..204bc78a9fdffcd11c397a85f94636bb17529b91 100755 (executable)
@@ -8,7 +8,8 @@ dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
-   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+   or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
+   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
@@ -26,6 +27,7 @@ cached=
 recursive=
 init=
 files=
+remote=
 nofetch=
 update=
 prefix=
@@ -152,6 +154,32 @@ die_if_unmatched ()
        fi
 }
 
+#
+# Print a submodule configuration setting
+#
+# $1 = submodule name
+# $2 = option name
+# $3 = default value
+#
+# Checks in the usual git-config places first (for overrides),
+# otherwise it falls back on .gitmodules.  This allows you to
+# distribute project-wide defaults in .gitmodules, while still
+# customizing individual repositories if necessary.  If the option is
+# not in .gitmodules either, print a default value.
+#
+get_submodule_config () {
+       name="$1"
+       option="$2"
+       default="$3"
+       value=$(git config submodule."$name"."$option")
+       if test -z "$value"
+       then
+               value=$(git config -f .gitmodules submodule."$name"."$option")
+       fi
+       printf '%s' "${value:-$default}"
+}
+
+
 #
 # Map submodule path to submodule name
 #
@@ -390,6 +418,10 @@ Use -f if you really want to add it." >&2
 
        git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
        git config -f .gitmodules submodule."$sm_name".url "$repo" &&
+       if test -n "$branch"
+       then
+               git config -f .gitmodules submodule."$sm_name".branch "$branch"
+       fi &&
        git add --force .gitmodules ||
        die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 }
@@ -515,6 +547,80 @@ cmd_init()
        done
 }
 
+#
+# Unregister submodules from .git/config and remove their work tree
+#
+# $@ = requested paths (use '.' to deinit all submodules)
+#
+cmd_deinit()
+{
+       # parse $args after "submodule ... deinit".
+       while test $# -ne 0
+       do
+               case "$1" in
+               -f|--force)
+                       force=$1
+                       ;;
+               -q|--quiet)
+                       GIT_QUIET=1
+                       ;;
+               --)
+                       shift
+                       break
+                       ;;
+               -*)
+                       usage
+                       ;;
+               *)
+                       break
+                       ;;
+               esac
+               shift
+       done
+
+       if test $# = 0
+       then
+               die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
+       fi
+
+       module_list "$@" |
+       while read mode sha1 stage sm_path
+       do
+               die_if_unmatched "$mode"
+               name=$(module_name "$sm_path") || exit
+
+               # 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
+                               echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
+                               die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
+                       fi
+
+                       if test -z "$force"
+                       then
+                               git rm -n "$sm_path" ||
+                               die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
+                       fi
+                       rm -rf "$sm_path" || say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
+               fi
+
+               mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
+
+               # 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 '\$sm_path'")"
+               fi
+       done
+}
+
 #
 # Update each submodule path to correct revision, using clone and checkout as needed
 #
@@ -533,6 +639,9 @@ cmd_update()
                -i|--init)
                        init=1
                        ;;
+               --remote)
+                       remote=1
+                       ;;
                -N|--no-fetch)
                        nofetch=1
                        ;;
@@ -593,6 +702,7 @@ cmd_update()
                fi
                name=$(module_name "$sm_path") || exit
                url=$(git config submodule."$name".url)
+               branch=$(get_submodule_config "$name" branch master)
                if ! test -z "$update"
                then
                        update_module=$update
@@ -627,6 +737,20 @@ Maybe you want to use 'update --init'?")"
                        die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
                fi
 
+               if test -n "$remote"
+               then
+                       if test -z "$nofetch"
+                       then
+                               # Fetch remote before determining tracking $sha1
+                               (clear_local_git_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" &&
+                               git rev-parse --verify "${remote_name}/${branch}") ||
+                       die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
+               fi
+
                if test "$subsha1" != "$sha1" -o -n "$force"
                then
                        subforce=$force
@@ -932,12 +1056,12 @@ cmd_summary() {
        done |
        if test -n "$for_status"; then
                if [ -n "$files" ]; then
-                       gettextln "# Submodules changed but not updated:"
+                       gettextln "Submodules changed but not updated:" | git stripspace -c
                else
-                       gettextln "# Submodule changes to be committed:"
+                       gettextln "Submodule changes to be committed:" | git stripspace -c
                fi
-               echo "#"
-               sed -e 's|^|# |' -e 's|^# $|#|'
+               printf "\n" | git stripspace -c
+               git stripspace -c
        else
                cat
        fi
@@ -1113,7 +1237,7 @@ cmd_sync()
 while test $# != 0 && test -z "$command"
 do
        case "$1" in
-       add | foreach | init | update | status | summary | sync)
+       add | foreach | init | deinit | update | status | summary | sync)
                command=$1
                ;;
        -q|--quiet)