gitweb: link to patch(es) view in commit(diff) and (short)log view
[gitweb.git] / git-submodule.sh
index 2d57d60458529e9b2816cdfd7f39df5dd5d99913..2f47e065fe8b7ca856f4527d6a507a28f1b2a06b 100755 (executable)
@@ -6,9 +6,10 @@
 
 USAGE="[--quiet] [--cached] \
 [add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
-[--] [<path>...]|[foreach <command>]"
+[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
 OPTIONS_SPEC=
 . git-sh-setup
+. git-parse-remote
 require_work_tree
 
 command=
@@ -30,12 +31,11 @@ say()
 # Resolve relative url by appending to parent's url
 resolve_relative_url ()
 {
-       branch="$(git symbolic-ref HEAD 2>/dev/null)"
-       remote="$(git config branch.${branch#refs/heads/}.remote)"
-       remote="${remote:-origin}"
+       remote=$(get_default_remote)
        remoteurl=$(git config "remote.$remote.url") ||
                die "remote ($remote) does not have a url defined in .git/config"
        url="$1"
+       remoteurl=${remoteurl%/}
        while test -n "$url"
        do
                case "$url" in
@@ -50,7 +50,16 @@ resolve_relative_url ()
                        break;;
                esac
        done
-       echo "$remoteurl/$url"
+       echo "$remoteurl/${url%/}"
+}
+
+#
+# Get submodule info for registered submodules
+# $@ = path to limit submodule list
+#
+module_list()
+{
+       git ls-files --stage -- "$@" | grep '^160000 '
 }
 
 #
@@ -185,7 +194,7 @@ cmd_add()
        else
 
                module_clone "$path" "$realrepo" || exit
-               (unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
+               (unset GIT_DIR; cd "$path" && git checkout -f -q ${branch:+-b "$branch" "origin/$branch"}) ||
                die "Unable to checkout submodule '$path'"
        fi
 
@@ -206,7 +215,7 @@ cmd_add()
 #
 cmd_foreach()
 {
-       git ls-files --stage | grep '^160000 ' |
+       module_list |
        while read mode sha1 stage path
        do
                if test -e "$path"/.git
@@ -246,7 +255,7 @@ cmd_init()
                shift
        done
 
-       git ls-files --stage -- "$@" | grep '^160000 ' |
+       module_list "$@" |
        while read mode sha1 stage path
        do
                # Skip already registered paths
@@ -304,7 +313,7 @@ cmd_update()
                esac
        done
 
-       git ls-files --stage -- "$@" | grep '^160000 ' |
+       module_list "$@" |
        while read mode sha1 stage path
        do
                name=$(module_name "$path") || exit
@@ -314,7 +323,7 @@ cmd_update()
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
-                       say "Submodule path '$path' not initialized"
+                       say "Submodule path '$path' not initialized" &&
                        say "Maybe you want to use 'update --init'?"
                        continue
                fi
@@ -331,8 +340,13 @@ cmd_update()
 
                if test "$subsha1" != "$sha1"
                then
+                       force=
+                       if test -z "$subsha1"
+                       then
+                               force="-f"
+                       fi
                        (unset GIT_DIR; cd "$path" && git-fetch &&
-                               git-checkout -q "$sha1") ||
+                               git-checkout $force -q "$sha1") ||
                        die "Unable to checkout '$sha1' in submodule path '$path'"
 
                        say "Submodule path '$path': checked out '$sha1'"
@@ -399,7 +413,7 @@ cmd_summary() {
 
        test $summary_limit = 0 && return
 
-       if rev=$(git rev-parse --verify "$1^0" 2>/dev/null)
+       if rev=$(git rev-parse -q --verify "$1^0")
        then
                head=$rev
                shift
@@ -410,7 +424,7 @@ cmd_summary() {
        cd_to_toplevel
        # Get modified modules cared by user
        modules=$(git diff-index $cached --raw $head -- "$@" |
-               grep -e '^:160000' -e '^:[0-7]* 160000' |
+               egrep '^:([0-7]* )?160000' |
                while read mod_src mod_dst sha1_src sha1_dst status name
                do
                        # Always show modules deleted or type-changed (blob<->module)
@@ -424,7 +438,7 @@ cmd_summary() {
        test -z "$modules" && return
 
        git diff-index $cached --raw $head -- $modules |
-       grep -e '^:160000' -e '^:[0-7]* 160000' |
+       egrep '^:([0-7]* )?160000' |
        cut -c2- |
        while read mod_src mod_dst sha1_src sha1_dst status name
        do
@@ -450,11 +464,11 @@ cmd_summary() {
                missing_dst=
 
                test $mod_src = 160000 &&
-               ! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_src^0 >/dev/null 2>&1 &&
+               ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
                missing_src=t
 
                test $mod_dst = 160000 &&
-               ! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_dst^0 >/dev/null 2>&1 &&
+               ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
                missing_dst=t
 
                total_commits=
@@ -569,7 +583,7 @@ cmd_status()
                shift
        done
 
-       git ls-files --stage -- "$@" | grep '^160000 ' |
+       module_list "$@" |
        while read mode sha1 stage path
        do
                name=$(module_name "$path") || exit
@@ -593,6 +607,58 @@ cmd_status()
                fi
        done
 }
+#
+# Sync remote urls for submodules
+# This makes the value for remote.$remote.url match the value
+# specified in .gitmodules.
+#
+cmd_sync()
+{
+       while test $# -ne 0
+       do
+               case "$1" in
+               -q|--quiet)
+                       quiet=1
+                       shift
+                       ;;
+               --)
+                       shift
+                       break
+                       ;;
+               -*)
+                       usage
+                       ;;
+               *)
+                       break
+                       ;;
+               esac
+       done
+       cd_to_toplevel
+       module_list "$@" |
+       while read mode sha1 stage path
+       do
+               name=$(module_name "$path")
+               url=$(git config -f .gitmodules --get submodule."$name".url)
+
+               # Possibly a url relative to parent
+               case "$url" in
+               ./*|../*)
+                       url=$(resolve_relative_url "$url") || exit
+                       ;;
+               esac
+
+               if test -e "$path"/.git
+               then
+               (
+                       unset GIT_DIR
+                       cd "$path"
+                       remote=$(get_default_remote)
+                       say "Synchronizing submodule url for '$name'"
+                       git config remote."$remote".url "$url"
+               )
+               fi
+       done
+}
 
 # This loop parses the command line arguments to find the
 # subcommand name to dispatch.  Parsing of the subcommand specific
@@ -603,7 +669,7 @@ cmd_status()
 while test $# != 0 && test -z "$command"
 do
        case "$1" in
-       add | foreach | init | update | status | summary)
+       add | foreach | init | update | status | summary | sync)
                command=$1
                ;;
        -q|--quiet)