fast-export: fix comparison in tests
[gitweb.git] / git-submodule.sh
index aac575e74f833c9bce28b779733b28a7611246b2..0522c3871a55d50cdada04c92db8d4bd87120df7 100755 (executable)
@@ -5,13 +5,13 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
+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] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
    or: $dashless [--quiet] foreach [--recursive] <command>
-   or: $dashless [--quiet] sync [--] [<path>...]"
+   or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
 OPTIONS_SPEC=
 . git-sh-setup
 . git-sh-i18n
@@ -29,6 +29,7 @@ files=
 nofetch=
 update=
 prefix=
+custom_name=
 
 # The function takes at most 2 arguments. The first argument is the
 # URL that navigates to the submodule origin repo. When relative, this URL
@@ -109,26 +110,48 @@ resolve_relative_url ()
 #
 module_list()
 {
-       git ls-files --error-unmatch --stage -- "$@" |
+       (
+               git ls-files --error-unmatch --stage -- "$@" ||
+               echo "unmatched pathspec exists"
+       ) |
        perl -e '
        my %unmerged = ();
        my ($null_sha1) = ("0" x 40);
+       my @out = ();
+       my $unmatched = 0;
        while (<STDIN>) {
+               if (/^unmatched pathspec/) {
+                       $unmatched = 1;
+                       next;
+               }
                chomp;
                my ($mode, $sha1, $stage, $path) =
                        /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
                next unless $mode eq "160000";
                if ($stage ne "0") {
                        if (!$unmerged{$path}++) {
-                               print "$mode $null_sha1 U\t$path\n";
+                               push @out, "$mode $null_sha1 U\t$path\n";
                        }
                        next;
                }
-               print "$_\n";
+               push @out, "$_\n";
+       }
+       if ($unmatched) {
+               print "#unmatched\n";
+       } else {
+               print for (@out);
        }
        '
 }
 
+die_if_unmatched ()
+{
+       if test "$1" = "#unmatched"
+       then
+               exit 1
+       fi
+}
+
 #
 # Map submodule path to submodule name
 #
@@ -157,8 +180,9 @@ module_name()
 module_clone()
 {
        sm_path=$1
-       url=$2
-       reference="$3"
+       name=$2
+       url=$3
+       reference="$4"
        quiet=
        if test -n "$GIT_QUIET"
        then
@@ -167,8 +191,6 @@ module_clone()
 
        gitdir=
        gitdir_base=
-       name=$(module_name "$sm_path" 2>/dev/null)
-       test -n "$name" || name="$sm_path"
        base_name=$(dirname "$name")
 
        gitdir=$(git rev-parse --git-dir)
@@ -248,6 +270,10 @@ cmd_add()
                        ;;
                --reference=*)
                        reference="$1"
+                       ;;
+               --name)
+                       case "$2" in '') usage ;; esac
+                       custom_name=$2
                        shift
                        ;;
                --)
@@ -314,6 +340,13 @@ Use -f if you really want to add it." >&2
                exit 1
        fi
 
+       if test -n "$custom_name"
+       then
+               sm_name="$custom_name"
+       else
+               sm_name="$sm_path"
+       fi
+
        # perhaps the path exists and is already a git repo, else clone it
        if test -e "$sm_path"
        then
@@ -325,8 +358,21 @@ Use -f if you really want to add it." >&2
                fi
 
        else
-
-               module_clone "$sm_path" "$realrepo" "$reference" || exit
+               if test -d ".git/modules/$sm_name"
+               then
+                       if test -z "$force"
+                       then
+                               echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")"
+                               GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^,"  ", -e s,' (fetch)',, >&2
+                               echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")"
+                               echo >&2 "  $realrepo"
+                               echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")"
+                               die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")"
+                       else
+                               echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
+                       fi
+               fi
+               module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" || exit
                (
                        clear_local_git_env
                        cd "$sm_path" &&
@@ -337,13 +383,13 @@ Use -f if you really want to add it." >&2
                        esac
                ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
        fi
-       git config submodule."$sm_path".url "$realrepo"
+       git config submodule."$sm_name".url "$realrepo"
 
        git add $force "$sm_path" ||
        die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
 
-       git config -f .gitmodules submodule."$sm_path".path "$sm_path" &&
-       git config -f .gitmodules submodule."$sm_path".url "$repo" &&
+       git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
+       git config -f .gitmodules submodule."$sm_name".url "$repo" &&
        git add --force .gitmodules ||
        die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 }
@@ -385,6 +431,7 @@ cmd_foreach()
        module_list |
        while read mode sha1 stage sm_path
        do
+               die_if_unmatched "$mode"
                if test -e "$sm_path"/.git
                then
                        say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
@@ -437,6 +484,7 @@ cmd_init()
        module_list "$@" |
        while read mode sha1 stage sm_path
        do
+               die_if_unmatched "$mode"
                name=$(module_name "$sm_path") || exit
 
                # Copy url setting when it is not set yet
@@ -537,6 +585,7 @@ cmd_update()
        err=
        while read mode sha1 stage sm_path
        do
+               die_if_unmatched "$mode"
                if test "$stage" = U
                then
                        echo >&2 "Skipping unmerged submodule $sm_path"
@@ -569,7 +618,7 @@ Maybe you want to use 'update --init'?")"
 
                if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
                then
-                       module_clone "$sm_path" "$url" "$reference"|| exit
+                       module_clone "$sm_path" "$name" "$url" "$reference" || exit
                        cloned_modules="$cloned_modules;$name"
                        subsha1=
                else
@@ -578,7 +627,7 @@ Maybe you want to use 'update --init'?")"
                        die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
                fi
 
-               if test "$subsha1" != "$sha1"
+               if test "$subsha1" != "$sha1" -o -n "$force"
                then
                        subforce=$force
                        # If we don't already have a -f flag and the submodule has never been checked out
@@ -901,7 +950,6 @@ cmd_summary() {
 cmd_status()
 {
        # parse $args after "submodule ... status".
-       orig_flags=
        while test $# -ne 0
        do
                case "$1" in
@@ -925,13 +973,13 @@ cmd_status()
                        break
                        ;;
                esac
-               orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
                shift
        done
 
        module_list "$@" |
        while read mode sha1 stage sm_path
        do
+               die_if_unmatched "$mode"
                name=$(module_name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                displaypath="$prefix$sm_path"
@@ -964,7 +1012,7 @@ cmd_status()
                                prefix="$displaypath/"
                                clear_local_git_env
                                cd "$sm_path" &&
-                               eval cmd_status "$orig_args"
+                               eval cmd_status
                        ) ||
                        die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
                fi
@@ -984,6 +1032,10 @@ cmd_sync()
                        GIT_QUIET=1
                        shift
                        ;;
+               --recursive)
+                       recursive=1
+                       shift
+                       ;;
                --)
                        shift
                        break
@@ -1000,6 +1052,7 @@ cmd_sync()
        module_list "$@" |
        while read mode sha1 stage sm_path
        do
+               die_if_unmatched "$mode"
                name=$(module_name "$sm_path")
                url=$(git config -f .gitmodules --get submodule."$name".url)
 
@@ -1024,7 +1077,7 @@ cmd_sync()
 
                if git config "submodule.$name.url" >/dev/null 2>/dev/null
                then
-                       say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
+                       say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
                        git config submodule."$name".url "$super_config_url"
 
                        if test -e "$sm_path"/.git
@@ -1034,6 +1087,12 @@ cmd_sync()
                                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
                fi
@@ -1080,7 +1139,15 @@ do
 done
 
 # No command word defaults to "status"
-test -n "$command" || command=status
+if test -z "$command"
+then
+    if test $# = 0
+    then
+       command=status
+    else
+       usage
+    fi
+fi
 
 # "-b branch" is accepted only by "add"
 if test -n "$branch" && test "$command" != add