# 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] 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>
- or: $dashless [--quiet] sync [--] [<path>...]"
+ or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
OPTIONS_SPEC=
. git-sh-setup
. git-sh-i18n
recursive=
init=
files=
+remote=
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
fi
}
+#
+# Print a submodule configuration setting
+#
+# $1 = submodule name
+# $2 = option name
+# $3 = default value
+#
+# Checks in the usual git-config places first (for overrides),
+# otherwise it falls back on .gitmodules. This allows you to
+# distribute project-wide defaults in .gitmodules, while still
+# customizing individual repositories if necessary. If the option is
+# not in .gitmodules either, print a default value.
+#
+get_submodule_config () {
+ name="$1"
+ option="$2"
+ default="$3"
+ value=$(git config submodule."$name"."$option")
+ if test -z "$value"
+ then
+ value=$(git config -f .gitmodules submodule."$name"."$option")
+ fi
+ printf '%s' "${value:-$default}"
+}
+
+
#
# 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" &&
+ if test -n "$branch"
+ then
+ git config -f .gitmodules submodule."$sm_name".branch "$branch"
+ fi &&
git add --force .gitmodules ||
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
}
-i|--init)
init=1
;;
+ --remote)
+ remote=1
+ ;;
-N|--no-fetch)
nofetch=1
;;
fi
name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
+ branch=$(get_submodule_config "$name" branch master)
if ! test -z "$update"
then
update_module=$update
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 -n "$remote"
+ then
+ if test -z "$nofetch"
+ then
+ # Fetch remote before determining tracking $sha1
+ (clear_local_git_env; cd "$sm_path" && git-fetch) ||
+ die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+ fi
+ remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
+ sha1=$(clear_local_git_env; cd "$sm_path" &&
+ git rev-parse --verify "${remote_name}/${branch}") ||
+ die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
+ fi
+
if test "$subsha1" != "$sha1" -o -n "$force"
then
subforce=$force
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
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
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