From: Junio C Hamano Date: Mon, 3 Sep 2012 22:54:17 +0000 (-0700) Subject: Merge branch 'sz/submodule-force-update' X-Git-Tag: v1.8.0-rc0~109 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/81dbbf72406c47b5199a59c6b83338b11fd3e754?ds=inline;hp=-c Merge branch 'sz/submodule-force-update' "git submodule update --force" used to leave the working tree of the submodule intact when there were local changes. It is more intiutive to make "--force" a sign to run "checkout -f" to overwrite them. * sz/submodule-force-update: Make 'git submodule update --force' always check out submodules. --- 81dbbf72406c47b5199a59c6b83338b11fd3e754 diff --combined git-submodule.sh index 08405249ed,812a60fe4c..3e2045e52d --- a/git-submodule.sh +++ b/git-submodule.sh @@@ -30,22 -30,7 +30,22 @@@ nofetch update= prefix= -# Resolve relative url by appending to parent's url +# The function takes at most 2 arguments. The first argument is the +# URL that navigates to the submodule origin repo. When relative, this URL +# is relative to the superproject origin URL repo. The second up_path +# argument, if specified, is the relative path that navigates +# from the submodule working tree to the superproject working tree. +# +# The output of the function is the origin URL of the submodule. +# +# The output will either be an absolute URL or filesystem path (if the +# superproject origin URL is an absolute URL or filesystem path, +# respectively) or a relative file system path (if the superproject +# origin URL is a relative file system path). +# +# When the output is a relative file system path, the path is either +# relative to the submodule working tree, if up_path is specified, or to +# the superproject working tree otherwise. resolve_relative_url () { remote=$(get_default_remote) @@@ -54,21 -39,6 +54,21 @@@ url="$1" remoteurl=${remoteurl%/} sep=/ + up_path="$2" + + case "$remoteurl" in + *:*|/*) + is_relative= + ;; + ./*|../*) + is_relative=t + ;; + *) + is_relative=t + remoteurl="./$remoteurl" + ;; + esac + while test -n "$url" do case "$url" in @@@ -83,12 -53,7 +83,12 @@@ sep=: ;; *) - die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")" + if test -z "$is_relative" || test "." = "$remoteurl" + then + die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")" + else + remoteurl=. + fi ;; esac ;; @@@ -99,8 -64,7 +99,8 @@@ break;; esac done - echo "$remoteurl$sep${url%/}" + remoteurl="$remoteurl$sep${url%/}" + echo "${is_relative:+${up_path}}${remoteurl#./}" } # @@@ -109,48 -73,26 +109,48 @@@ # 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 () { + 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 # @@@ -203,18 -145,13 +203,18 @@@ module_clone( rm -f "$gitdir/index" else mkdir -p "$gitdir_base" - git clone $quiet -n ${reference:+"$reference"} \ - --separate-git-dir "$gitdir" "$url" "$sm_path" || + ( + clear_local_git_env + git clone $quiet -n ${reference:+"$reference"} \ + --separate-git-dir "$gitdir" "$url" "$sm_path" + ) || die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")" fi - a=$(cd "$gitdir" && pwd)/ - b=$(cd "$sm_path" && pwd)/ + # We already are at the root of the work tree but cd_to_toplevel will + # resolve any symlinks that might be present in $PWD + a=$(cd_to_toplevel && cd "$gitdir" && pwd)/ + b=$(cd_to_toplevel && cd "$sm_path" && pwd)/ # normalize Windows-style absolute paths to POSIX-style absolute paths case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac @@@ -407,7 -344,6 +407,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'")" @@@ -460,7 -396,6 +460,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 @@@ -561,7 -496,6 +561,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" @@@ -603,7 -537,7 +603,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 @@@ -776,7 -710,7 +776,7 @@@ cmd_summary() if [ -n "$files" ] then test -n "$cached" && - die "$(gettext -- "--cached cannot be used with --files")" + die "$(gettext "The --cached option cannot be used with the --files option")" diff_cmd=diff-files head= fi @@@ -957,7 -891,6 +957,7 @@@ cmd_status( 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" @@@ -1026,33 -959,20 +1026,33 @@@ 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) # Possibly a url relative to parent case "$url" in ./*|../*) - url=$(resolve_relative_url "$url") || exit + # rewrite foo/bar as ../.. to find path from + # submodule work tree to superproject work tree + up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" && + # guarantee a trailing / + up_path=${up_path%/}/ && + # path from submodule work tree to submodule origin repo + sub_origin_url=$(resolve_relative_url "$url" "$up_path") && + # path from superproject work tree to submodule origin repo + super_config_url=$(resolve_relative_url "$url") || exit + ;; + *) + sub_origin_url="$url" + super_config_url="$url" ;; esac if git config "submodule.$name.url" >/dev/null 2>/dev/null then say "$(eval_gettext "Synchronizing submodule url for '\$name'")" - git config submodule."$name".url "$url" + git config submodule."$name".url "$super_config_url" if test -e "$sm_path"/.git then @@@ -1060,7 -980,7 +1060,7 @@@ clear_local_git_env cd "$sm_path" remote=$(get_default_remote) - git config remote."$remote".url "$url" + git config remote."$remote".url "$sub_origin_url" ) fi fi diff --combined t/t7406-submodule-update.sh index 646298b212,8e9c380c47..15426530e4 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@@ -123,6 -123,18 +123,18 @@@ test_expect_success 'submodule update s ) ' + test_expect_success 'submodule update --force forcibly checks out submodules' ' + (cd super && + (cd submodule && + rm -f file + ) && + git submodule update --force submodule && + (cd submodule && + test "$(git status -s file)" = "" + ) + ) + ' + test_expect_success 'submodule update --rebase staying on master' ' (cd super/submodule && git checkout master @@@ -367,7 -379,7 +379,7 @@@ test_expect_success 'submodule update c git submodule init && git commit -am "new_submodule" && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../expect + git rev-parse --verify HEAD >../expect ) && (cd submodule && test_commit "update_submodule" file @@@ -384,7 -396,7 +396,7 @@@ git checkout HEAD^ && test_must_fail git submodule update && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../actual + git rev-parse --verify HEAD >../actual ) && test_cmp expect actual ) @@@ -413,7 -425,7 +425,7 @@@ test_expect_success 'submodule update c test_commit "update_submodule_again_again" file ) && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../expect && + git rev-parse --verify HEAD >../expect && test_commit "update_submodule2_again" file ) && git add submodule && @@@ -428,7 -440,7 +440,7 @@@ ) && test_must_fail git submodule update --recursive && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../actual + git rev-parse --verify HEAD >../actual ) && test_cmp expect actual ) @@@ -460,12 -472,12 +472,12 @@@ test_expect_success 'submodule update e ) && git checkout HEAD^ && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../expect + git rev-parse --verify HEAD >../expect ) && git config submodule.submodule.update merge && test_must_fail git submodule update && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../actual + git rev-parse --verify HEAD >../actual ) && test_cmp expect actual ) @@@ -495,12 -507,12 +507,12 @@@ test_expect_success 'submodule update e ) && git checkout HEAD^ && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../expect + git rev-parse --verify HEAD >../expect ) && git config submodule.submodule.update rebase && test_must_fail git submodule update && (cd submodule2 && - git rev-parse --max-count=1 HEAD > ../actual + git rev-parse --verify HEAD >../actual ) && test_cmp expect actual ) @@@ -636,17 -648,4 +648,17 @@@ test_expect_success 'submodule update p ) ' +test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd' ' + mkdir -p linked/dir && + ln -s linked/dir linkto && + ( + cd linkto && + git clone "$TRASH_DIRECTORY"/super_update_r2 super && + ( + cd super && + git submodule update --init --recursive + ) + ) +' + test_done