# 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
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
#
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
#
module_clone()
{
sm_path=$1
- url=$2
- reference="$3"
+ name=$2
+ url=$3
+ reference="$4"
quiet=
if test -n "$GIT_QUIET"
then
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)
;;
--reference=*)
reference="$1"
+ ;;
+ --name)
+ case "$2" in '') usage ;; esac
+ custom_name=$2
shift
;;
--)
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
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" &&
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'")"
}
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'")"
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
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"
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
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
cmd_status()
{
# parse $args after "submodule ... status".
- orig_flags=
while test $# -ne 0
do
case "$1" in
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"
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
GIT_QUIET=1
shift
;;
+ --recursive)
+ recursive=1
+ shift
+ ;;
--)
shift
break
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)
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
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
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