am: return control to caller, for housekeeping
[gitweb.git] / git-submodule.sh
index 004c034bc09449416ff6d66b7570d48b651f96cb..79bfaac9d4cb9a04e5e1fd7675d740cf9fc27e87 100755 (executable)
@@ -8,6 +8,7 @@ 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] 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>
@@ -266,6 +267,11 @@ module_clone()
        (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
 }
 
+isnumber()
+{
+       n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
+}
+
 #
 # Add a new submodule to the working tree, .gitmodules and the index
 #
@@ -546,6 +552,82 @@ 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 -qn "$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 "Cleared directory '\$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
 #
@@ -622,7 +704,7 @@ cmd_update()
                die_if_unmatched "$mode"
                if test "$stage" = U
                then
-                       echo >&2 "Skipping unmerged submodule $sm_path"
+                       echo >&2 "Skipping unmerged submodule $prefix$sm_path"
                        continue
                fi
                name=$(module_name "$sm_path") || exit
@@ -637,7 +719,7 @@ cmd_update()
 
                if test "$update_module" = "none"
                then
-                       echo "Skipping submodule '$sm_path'"
+                       echo "Skipping submodule '$prefix$sm_path'"
                        continue
                fi
 
@@ -646,7 +728,7 @@ cmd_update()
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
-                       say "$(eval_gettext "Submodule path '\$sm_path' not initialized
+                       say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
 Maybe you want to use 'update --init'?")"
                        continue
                fi
@@ -659,7 +741,7 @@ Maybe you want to use 'update --init'?")"
                else
                        subsha1=$(clear_local_git_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
-                       die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
+                       die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
                fi
 
                if test -n "$remote"
@@ -692,7 +774,7 @@ Maybe you want to use 'update --init'?")"
                                (clear_local_git_env; cd "$sm_path" &&
                                        ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
                                         test -z "$rev") || git-fetch)) ||
-                               die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+                               die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
                        fi
 
                        # Is this something we just cloned?
@@ -706,20 +788,20 @@ Maybe you want to use 'update --init'?")"
                        case "$update_module" in
                        rebase)
                                command="git rebase"
-                               die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        merge)
                                command="git merge"
-                               die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': merged in '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        *)
                                command="git checkout $subforce -q"
-                               die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': checked out '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
                                ;;
                        esac
 
@@ -737,11 +819,16 @@ Maybe you want to use 'update --init'?")"
 
                if test -n "$recursive"
                then
-                       (clear_local_git_env; cd "$sm_path" && eval cmd_update "$orig_flags")
+                       (
+                               prefix="$prefix$sm_path/"
+                               clear_local_git_env
+                               cd "$sm_path" &&
+                               eval cmd_update "$orig_flags"
+                       )
                        res=$?
                        if test $res -gt 0
                        then
-                               die_msg="$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
+                               die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
                                if test $res -eq 1
                                then
                                        err="${err};$die_msg"
@@ -809,14 +896,14 @@ cmd_summary() {
                        for_status="$1"
                        ;;
                -n|--summary-limit)
-                       if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
-                       then
-                               :
-                       else
-                               usage
-                       fi
+                       summary_limit="$2"
+                       isnumber "$summary_limit" || usage
                        shift
                        ;;
+               --summary-limit=*)
+                       summary_limit="${1#--summary-limit=}"
+                       isnumber "$summary_limit" || usage
+                       ;;
                --)
                        shift
                        break
@@ -1157,7 +1244,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)