From: Jeff King Date: Mon, 29 Oct 2012 08:12:12 +0000 (-0400) Subject: Merge branch 'jl/submodule-add-by-name' X-Git-Tag: v1.8.1-rc0~99 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/fdb4d27158e4f8e19ac3b11b896bff92038afbfa?ds=inline;hp=-c Merge branch 'jl/submodule-add-by-name' If you remove a submodule, in order to keep the repository so that "git checkout" to an older commit in the superproject history can resurrect the submodule, the real repository will stay in $GIT_DIR of the superproject. A later "git submodule add $path" to add a different submodule at the same path will fail. Diagnose this case a bit better, and if the user really wants to add an unrelated submodule at the same path, give the "--name" option to give it a place in $GIT_DIR of the superproject that does not conflict with the original submodule. * jl/submodule-add-by-name: submodule add: Fail when .git/modules/ already exists unless forced Teach "git submodule add" the --name option --- fdb4d27158e4f8e19ac3b11b896bff92038afbfa diff --combined Documentation/git-submodule.txt index b4683bba1b,22efca01b7..1d6527ab9f --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@@ -9,7 -9,7 +9,7 @@@ git-submodule - Initialize, update or i SYNOPSIS -------- [verse] - 'git submodule' [--quiet] add [-b branch] [-f|--force] + 'git submodule' [--quiet] add [-b branch] [-f|--force] [--name ] [--reference ] [--] [] 'git submodule' [--quiet] status [--cached] [--recursive] [--] [...] 'git submodule' [--quiet] init [--] [...] @@@ -112,6 -112,7 +112,6 @@@ status: initialized, `+` if the currently checked out submodule commit does not match the SHA-1 found in the index of the containing repository and `U` if the submodule has merge conflicts. - This command is the default command for 'git submodule'. + If `--recursive` is specified, this command will recurse into nested submodules, and show their status as well. @@@ -265,6 -266,11 +265,11 @@@ OPTION Initialize all submodules for which "git submodule init" has not been called so far before updating. + --name:: + This option is only valid for the add command. It sets the submodule's + name to the given string instead of defaulting to its path. The name + must be valid as a directory name and may not end with a '/'. + --reference :: This option is only valid for add and update commands. These commands sometimes need to clone a remote repository. In this case, diff --combined git-submodule.sh index ab6b1107b6,e8112c8d1a..9e1e1f4410 --- a/git-submodule.sh +++ b/git-submodule.sh @@@ -5,7 -5,7 +5,7 @@@ # Copyright (c) 2007 Lars Hjemli dashless=$(basename "$0" | sed -e 's/-/ /') - USAGE="[--quiet] add [-b branch] [-f|--force] [--reference ] [--] [] + USAGE="[--quiet] add [-b branch] [-f|--force] [--name ] [--reference ] [--] [] or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] @@@ -29,6 -29,7 +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 @@@ -179,8 -180,9 +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 @@@ -189,8 -191,6 +191,6 @@@ 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) @@@ -272,6 -272,11 +272,11 @@@ cmd_add( reference="$1" shift ;; + --name) + case "$2" in '') usage ;; esac + custom_name=$2 + shift + ;; --) shift break @@@ -336,6 -341,13 +341,13 @@@ Use -f if you really want to add it." > 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 @@@ -347,8 -359,21 +359,21 @@@ 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" && @@@ -359,13 -384,13 +384,13 @@@ 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'")" } @@@ -594,7 -619,7 +619,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 @@@ -1107,15 -1132,7 +1132,15 @@@ d 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 diff --combined t/t7400-submodule-basic.sh index 5397037491,f1a94f7ca1..de7d45352e --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@@ -438,8 -438,8 +438,8 @@@ test_expect_success 'moving to a commi git checkout second ' -test_expect_success 'submodule warns' ' - test_failure_with_unknown_submodule +test_expect_success 'submodule fails' ' + test_must_fail git submodule no-such-subcommand ' test_expect_success 'add submodules without specifying an explicit path' ' @@@ -681,4 -681,79 +681,79 @@@ test_expect_success 'moving the superpr ) ' + test_expect_success 'submodule add --name allows to replace a submodule with another at the same path' ' + ( + cd addtest2 && + ( + cd repo && + echo "$submodurl/repo" >expect && + git config remote.origin.url >actual && + test_cmp expect actual && + echo "gitdir: ../.git/modules/repo" >expect && + test_cmp expect .git + ) && + rm -rf repo && + git rm repo && + git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual && + test ! -s actual && + echo "gitdir: ../.git/modules/submod" >expect && + test_cmp expect submod/.git && + ( + cd repo && + echo "$submodurl/bare.git" >expect && + git config remote.origin.url >actual && + test_cmp expect actual && + echo "gitdir: ../.git/modules/repo_new" >expect && + test_cmp expect .git + ) && + echo "repo" >expect && + git config -f .gitmodules submodule.repo.path >actual && + test_cmp expect actual && + git config -f .gitmodules submodule.repo_new.path >actual && + test_cmp expect actual&& + echo "$submodurl/repo" >expect && + git config -f .gitmodules submodule.repo.url >actual && + test_cmp expect actual && + echo "$submodurl/bare.git" >expect && + git config -f .gitmodules submodule.repo_new.url >actual && + test_cmp expect actual && + echo "$submodurl/repo" >expect && + git config submodule.repo.url >actual && + test_cmp expect actual && + echo "$submodurl/bare.git" >expect && + git config submodule.repo_new.url >actual && + test_cmp expect actual + ) + ' + + test_expect_success 'submodule add with an existing name fails unless forced' ' + ( + cd addtest2 && + rm -rf repo && + git rm repo && + test_must_fail git submodule add -q --name repo_new "$submodurl/repo.git" repo && + test ! -d repo && + echo "repo" >expect && + git config -f .gitmodules submodule.repo_new.path >actual && + test_cmp expect actual&& + echo "$submodurl/bare.git" >expect && + git config -f .gitmodules submodule.repo_new.url >actual && + test_cmp expect actual && + echo "$submodurl/bare.git" >expect && + git config submodule.repo_new.url >actual && + test_cmp expect actual && + git submodule add -f -q --name repo_new "$submodurl/repo.git" repo && + test -d repo && + echo "repo" >expect && + git config -f .gitmodules submodule.repo_new.path >actual && + test_cmp expect actual&& + echo "$submodurl/repo.git" >expect && + git config -f .gitmodules submodule.repo_new.url >actual && + test_cmp expect actual && + echo "$submodurl/repo.git" >expect && + git config submodule.repo_new.url >actual && + test_cmp expect actual + ) + ' + test_done