git-submodule: add support for --rebase.
[gitweb.git] / git-submodule.sh
index 2f47e065fe8b7ca856f4527d6a507a28f1b2a06b..3176226ac7ecca9dc875a20bd5c2df607cdfb504 100755 (executable)
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 USAGE="[--quiet] [--cached] \
-[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
+[add [-b branch] <repo> <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
 [--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
 OPTIONS_SPEC=
 . git-sh-setup
@@ -16,6 +16,8 @@ command=
 branch=
 quiet=
 cached=
+nofetch=
+rebase=
 
 #
 # print stuff on stdout unless -q was specified
@@ -59,7 +61,7 @@ resolve_relative_url ()
 #
 module_list()
 {
-       git ls-files --stage -- "$@" | grep '^160000 '
+       git ls-files --error-unmatch --stage -- "$@" | grep '^160000 '
 }
 
 #
@@ -166,9 +168,18 @@ cmd_add()
        ;;
        esac
 
-       # strip trailing slashes from path
-       path=$(echo "$path" | sed -e 's|/*$||')
-
+       # normalize path:
+       # multiple //; leading ./; /./; /../; trailing /
+       path=$(printf '%s/\n' "$path" |
+               sed -e '
+                       s|//*|/|g
+                       s|^\(\./\)*||
+                       s|/\./|/|g
+                       :start
+                       s|\([^/]*\)/\.\./||
+                       tstart
+                       s|/*$||
+               ')
        git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
        die "'$path' already exists in the index"
 
@@ -194,8 +205,15 @@ cmd_add()
        else
 
                module_clone "$path" "$realrepo" || exit
-               (unset GIT_DIR; cd "$path" && git checkout -f -q ${branch:+-b "$branch" "origin/$branch"}) ||
-               die "Unable to checkout submodule '$path'"
+               (
+                       unset GIT_DIR
+                       cd "$path" &&
+                       # ash fails to wordsplit ${branch:+-b "$branch"...}
+                       case "$branch" in
+                       '') git checkout -f -q ;;
+                       ?*) git checkout -f -q -b "$branch" "origin/$branch" ;;
+                       esac
+               ) || die "Unable to checkout submodule '$path'"
        fi
 
        git add "$path" ||
@@ -277,6 +295,11 @@ cmd_init()
                git config submodule."$name".url "$url" ||
                die "Failed to register url for submodule path '$path'"
 
+               test true != "$(git config -f .gitmodules --bool \
+                       submodule."$name".rebase)" ||
+               git config submodule."$name".rebase true ||
+               die "Failed to register submodule path '$path' as rebasing"
+
                say "Submodule '$name' ($url) registered for path '$path'"
        done
 }
@@ -300,6 +323,14 @@ cmd_update()
                        shift
                        cmd_init "$@" || return
                        ;;
+               -N|--no-fetch)
+                       shift
+                       nofetch=1
+                       ;;
+               -r|--rebase)
+                       shift
+                       rebase=true
+                       ;;
                --)
                        shift
                        break
@@ -318,6 +349,7 @@ cmd_update()
        do
                name=$(module_name "$path") || exit
                url=$(git config submodule."$name".url)
+               rebase_module=$(git config --bool submodule."$name".rebase)
                if test -z "$url"
                then
                        # Only mention uninitialized submodules when its
@@ -338,6 +370,11 @@ cmd_update()
                        die "Unable to find current revision in submodule path '$path'"
                fi
 
+               if test true = "$rebase"
+               then
+                       rebase_module=true
+               fi
+
                if test "$subsha1" != "$sha1"
                then
                        force=
@@ -345,11 +382,28 @@ cmd_update()
                        then
                                force="-f"
                        fi
-                       (unset GIT_DIR; cd "$path" && git-fetch &&
-                               git-checkout $force -q "$sha1") ||
-                       die "Unable to checkout '$sha1' in submodule path '$path'"
 
-                       say "Submodule path '$path': checked out '$sha1'"
+                       if test -z "$nofetch"
+                       then
+                               (unset GIT_DIR; cd "$path" &&
+                                       git-fetch) ||
+                               die "Unable to fetch in submodule path '$path'"
+                       fi
+
+                       if test true = "$rebase_module"
+                       then
+                               command="git-rebase"
+                               action="rebase"
+                               msg="rebased onto"
+                       else
+                               command="git-checkout $force -q"
+                               action="checkout"
+                               msg="checked out"
+                       fi
+
+                       (unset GIT_DIR; cd "$path" && $command "$sha1") ||
+                       die "Unable to $action '$sha1' in submodule path '$path'"
+                       say "Submodule path '$path': $msg '$sha1'"
                fi
        done
 }