X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=git-submodule.sh;h=58713c5467f02dd79efefd4534373757af81713e;hb=032568d6427d50d5e28c2088db991b117a2be711;hp=136e26a2c8d4ca1e835e2873f3fd994864dc135e;hpb=e0c2b742e0fece8aeee415331f0b988dd7765abd;p=platform%2Fupstream%2Fgit.git diff --git a/git-submodule.sh b/git-submodule.sh index 136e26a..58713c5 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -5,11 +5,13 @@ # Copyright (c) 2007 Lars Hjemli dashless=$(basename "$0" | sed -e 's/-/ /') -USAGE="[--quiet] add [-b ] [-f|--force] [--name ] [--reference ] [--] [] +USAGE="[--quiet] [--cached] + or: $dashless [--quiet] add [-b ] [-f|--force] [--name ] [--reference ] [--] [] or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] or: $dashless [--quiet] deinit [-f|--force] (--all| [--] ...) or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference ] [--recursive] [--] [...] + or: $dashless [--quiet] set-branch (--default|--branch ) [--] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] or: $dashless [--quiet] sync [--recursive] [--] [...] @@ -34,6 +36,7 @@ reference= cached= recursive= init= +require_init= files= remote= nofetch= @@ -42,6 +45,7 @@ prefix= custom_name= depth= progress= +dissociate= die_if_unmatched () { @@ -71,7 +75,7 @@ get_submodule_config () { value=$(git config submodule."$name"."$option") if test -z "$value" then - value=$(git config -f .gitmodules submodule."$name"."$option") + value=$(git submodule--helper config submodule."$name"."$option") fi printf '%s' "${value:-$default}" } @@ -81,6 +85,11 @@ isnumber() n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1" } +# Given a full hex object ID, is this the zero OID? +is_zero_oid () { + echo "$1" | sane_egrep '^0+$' >/dev/null 2>&1 +} + # Sanitize the local git environment for use within a submodule. We # can't simply use clear_local_git_env since we want to preserve some # of the settings from GIT_CONFIG_PARAMETERS. @@ -117,6 +126,9 @@ cmd_add() -q|--quiet) GIT_QUIET=1 ;; + --progress) + progress=1 + ;; --reference) case "$2" in '') usage ;; esac reference_path=$2 @@ -125,6 +137,9 @@ cmd_add() --reference=*) reference_path="${1#--reference=}" ;; + --dissociate) + dissociate=1 + ;; --name) case "$2" in '') usage ;; esac custom_name=$2 @@ -152,6 +167,11 @@ cmd_add() shift done + if ! git submodule--helper config --check-writeable >/dev/null 2>&1 + then + die "$(eval_gettext "please make sure that the .gitmodules file is in the working tree")" + fi + if test -n "$reference_path" then is_absolute_path "$reference_path" || @@ -213,7 +233,15 @@ cmd_add() die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")" fi - if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1 + if test -d "$sm_path" && + test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null) + then + git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null || + die "$(eval_gettext "'\$sm_path' does not have a commit checked out")" + fi + + if test -z "$force" && + ! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1 then eval_gettextln "The following path is ignored by one of your .gitignore files: \$sm_path @@ -228,6 +256,11 @@ Use -f if you really want to add it." >&2 sm_name="$sm_path" fi + if ! git submodule--helper check-name "$sm_name" + then + die "$(eval_gettext "'$sm_name' is not a valid submodule name")" + fi + # perhaps the path exists and is already a git repo, else clone it if test -e "$sm_path" then @@ -254,7 +287,7 @@ or you are unsure what this means choose another name with the '--name' option." eval_gettextln "Reactivating local git directory for submodule '\$sm_name'." fi fi - git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${depth:+"$depth"} || exit + git submodule--helper clone ${GIT_QUIET:+--quiet} ${progress:+"--progress"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit ( sanitize_submodule_env cd "$sm_path" && @@ -267,17 +300,31 @@ or you are unsure what this means choose another name with the '--name' option." fi git config submodule."$sm_name".url "$realrepo" - git add $force "$sm_path" || + git add --no-warn-embedded-repo $force "$sm_path" || die "$(eval_gettext "Failed to add submodule '\$sm_path'")" - git config -f .gitmodules submodule."$sm_name".path "$sm_path" && - git config -f .gitmodules submodule."$sm_name".url "$repo" && + git submodule--helper config submodule."$sm_name".path "$sm_path" && + git submodule--helper config submodule."$sm_name".url "$repo" && if test -n "$branch" then - git config -f .gitmodules submodule."$sm_name".branch "$branch" + git submodule--helper config submodule."$sm_name".branch "$branch" fi && git add --force .gitmodules || die "$(eval_gettext "Failed to register submodule '\$sm_path'")" + + # NEEDSWORK: In a multi-working-tree world, this needs to be + # set in the per-worktree config. + if git config --get submodule.active >/dev/null + then + # If the submodule being adding isn't already covered by the + # current configured pathspec, set the submodule's active flag + if ! git submodule--helper is-active "$sm_path" + then + git config submodule."$sm_name".active "true" + fi + else + git config submodule."$sm_name".active "true" + fi } # @@ -308,45 +355,7 @@ cmd_foreach() shift done - toplevel=$(pwd) - - # dup stdin so that it can be restored when running the external - # command in the subshell (and a recursive call to this function) - exec 3<&0 - - { - git submodule--helper list --prefix "$wt_prefix" || - echo "#unmatched" $? - } | - while read mode sha1 stage sm_path - do - die_if_unmatched "$mode" "$sha1" - if test -e "$sm_path"/.git - then - displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") - say "$(eval_gettext "Entering '\$displaypath'")" - name=$(git submodule--helper name "$sm_path") - ( - prefix="$prefix$sm_path/" - sanitize_submodule_env - cd "$sm_path" && - sm_path=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") && - # we make $path available to scripts ... - path=$sm_path && - if test $# -eq 1 - then - eval "$1" - else - "$@" - fi && - if test -n "$recursive" - then - cmd_foreach "--recursive" "$@" - fi - ) <&3 3<&- || - die "$(eval_gettext "Stopping at '\$displaypath'; script returned non-zero status.")" - fi - done + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" } # @@ -377,7 +386,7 @@ cmd_init() shift done - git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} "$@" + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@" } # @@ -413,60 +422,7 @@ cmd_deinit() shift done - if test -n "$deinit_all" && test "$#" -ne 0 - then - echo >&2 "$(eval_gettext "pathspec and --all are incompatible")" - usage - fi - if test $# = 0 && test -z "$deinit_all" - then - die "$(eval_gettext "Use '--all' if you really want to deinitialize all submodules")" - fi - - { - git submodule--helper list --prefix "$wt_prefix" "$@" || - echo "#unmatched" $? - } | - while read mode sha1 stage sm_path - do - die_if_unmatched "$mode" "$sha1" - name=$(git submodule--helper name "$sm_path") || exit - - displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix") - - # Remove the submodule work tree (unless the user already did it) - if test -d "$sm_path" - then - # Protect submodules containing a .git directory - if test -d "$sm_path/.git" - then - die "$(eval_gettext "\ -Submodule work tree '\$displaypath' contains a .git directory -(use 'rm -rf' if you really want to remove it including all of its history)")" - fi - - if test -z "$force" - then - git rm -qn "$sm_path" || - die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")" - fi - rm -rf "$sm_path" && - say "$(eval_gettext "Cleared directory '\$displaypath'")" || - say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")" - fi - - mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")" - - # Remove the .git/config entries (unless the user already did it) - if test -n "$(git config --get-regexp submodule."$name\.")" - then - # Remove the whole section so we have a clean state when - # the user later decides to init this submodule again - url=$(git config submodule."$name".url) - git config --remove-section submodule."$name" 2>/dev/null && - say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")" - fi - done + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} -- "$@" } is_tip_reachable () ( @@ -502,12 +458,19 @@ cmd_update() -q|--quiet) GIT_QUIET=1 ;; + -v) + GIT_QUIET=0 + ;; --progress) - progress="--progress" + progress=1 ;; -i|--init) init=1 ;; + --require-init) + init=1 + require_init=1 + ;; --remote) remote=1 ;; @@ -528,6 +491,9 @@ cmd_update() --reference=*) reference="$1" ;; + --dissociate) + dissociate=1 + ;; -m|--merge) update="merge" ;; @@ -580,43 +546,33 @@ cmd_update() { git submodule--helper update-clone ${GIT_QUIET:+--quiet} \ - ${progress:+"$progress"} \ + ${progress:+"--progress"} \ ${wt_prefix:+--prefix "$wt_prefix"} \ ${prefix:+--recursive-prefix "$prefix"} \ ${update:+--update "$update"} \ ${reference:+"$reference"} \ + ${dissociate:+"--dissociate"} \ ${depth:+--depth "$depth"} \ - ${recommend_shallow:+"$recommend_shallow"} \ - ${jobs:+$jobs} \ + ${require_init:+--require-init} \ + $recommend_shallow \ + $jobs \ + -- \ "$@" || echo "#unmatched" $? } | { err= - while read mode sha1 stage just_cloned sm_path + while read -r quickabort sha1 just_cloned sm_path do - die_if_unmatched "$mode" "$sha1" + die_if_unmatched "$quickabort" "$sha1" - name=$(git submodule--helper name "$sm_path") || exit - url=$(git config submodule."$name".url) - if ! test -z "$update" - then - update_module=$update - else - update_module=$(git config submodule."$name".update) - if test -z "$update_module" - then - update_module="checkout" - fi - fi + git submodule--helper ensure-core-worktree "$sm_path" || exit 1 + + update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update) displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") if test $just_cloned -eq 1 then subsha1= - case "$update_module" in - merge | rebase | none) - update_module=checkout ;; - esac else subsha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD) || @@ -653,7 +609,7 @@ cmd_update() # is not reachable from a ref. is_tip_reachable "$sm_path" "$sha1" || fetch_in_submodule "$sm_path" $depth || - die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")" + say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'; trying to directly fetch \$sha1:")" # Now we tried the usual fetch, but $sha1 may # not be reachable from any of the refs @@ -688,7 +644,7 @@ cmd_update() must_die_on_failure=yes ;; *) - die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")" + die "$(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")" esac if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1") @@ -744,18 +700,72 @@ cmd_update() } } -set_name_rev () { - revname=$( ( - sanitize_submodule_env - cd "$1" && { - git describe "$2" 2>/dev/null || - git describe --tags "$2" 2>/dev/null || - git describe --contains "$2" 2>/dev/null || - git describe --all --always "$2" - } - ) ) - test -z "$revname" || revname=" ($revname)" +# +# Configures a submodule's default branch +# +# $@ = requested path +# +cmd_set_branch() { + unset_branch=false + branch= + + while test $# -ne 0 + do + case "$1" in + -q|--quiet) + # we don't do anything with this but we need to accept it + ;; + -d|--default) + unset_branch=true + ;; + -b|--branch) + case "$2" in '') usage ;; esac + branch=$2 + shift + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + if test $# -ne 1 + then + usage + fi + + # we can't use `git submodule--helper name` here because internally, it + # hashes the path so a trailing slash could lead to an unintentional no match + name="$(git submodule--helper list "$1" | cut -f2)" + if test -z "$name" + then + exit 1 + fi + + test -n "$branch"; has_branch=$? + test "$unset_branch" = true; has_unset_branch=$? + + if test $((!$has_branch != !$has_unset_branch)) -eq 0 + then + usage + fi + + if test $has_branch -eq 0 + then + git submodule--helper config submodule."$name".branch "$branch" + else + git submodule--helper config --unset submodule."$name".branch + fi } + # # Show commit summary for submodules in index or working tree # @@ -833,7 +843,7 @@ cmd_summary() { # Get modified modules cared by user modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" | sane_egrep '^:([0-7]* )?160000' | - while read mod_src mod_dst sha1_src sha1_dst status sm_path + while read -r mod_src mod_dst sha1_src sha1_dst status sm_path do # Always show modules deleted or type-changed (blob<->module) if test "$status" = D || test "$status" = T @@ -849,7 +859,7 @@ cmd_summary() { test $status != A && test $ignore_config = all && continue fi # Also show added or modified modules which are checked out - GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 && + GIT_DIR="$sm_path/.git" git rev-parse --git-dir >/dev/null 2>&1 && printf '%s\n' "$sm_path" done ) @@ -859,10 +869,10 @@ cmd_summary() { git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules | sane_egrep '^:([0-7]* )?160000' | cut -c2- | - while read mod_src mod_dst sha1_src sha1_dst status name + while read -r mod_src mod_dst sha1_src sha1_dst status name do if test -z "$cached" && - test $sha1_dst = 0000000000000000000000000000000000000000 + is_zero_oid $sha1_dst then case "$mod_dst" in 160000) @@ -883,11 +893,11 @@ cmd_summary() { missing_dst= test $mod_src = 160000 && - ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null && + ! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_src^0 >/dev/null && missing_src=t test $mod_dst = 160000 && - ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null && + ! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_dst^0 >/dev/null && missing_dst=t display_name=$(git submodule--helper relative-path "$name" "$wt_prefix") @@ -922,8 +932,11 @@ cmd_summary() { ;; esac - sha1_abbr_src=$(echo $sha1_src | cut -c1-7) - sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7) + sha1_abbr_src=$(GIT_DIR="$name/.git" git rev-parse --short $sha1_src 2>/dev/null || + echo $sha1_src | cut -c1-7) + sha1_abbr_dst=$(GIT_DIR="$name/.git" git rev-parse --short $sha1_dst 2>/dev/null || + echo $sha1_dst | cut -c1-7) + if test $status = T then blob="$(gettext "blob")" @@ -1002,55 +1015,7 @@ cmd_status() shift done - { - git submodule--helper list --prefix "$wt_prefix" "$@" || - echo "#unmatched" $? - } | - while read mode sha1 stage sm_path - do - die_if_unmatched "$mode" "$sha1" - name=$(git submodule--helper name "$sm_path") || exit - url=$(git config submodule."$name".url) - displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") - if test "$stage" = U - then - say "U$sha1 $displaypath" - continue - fi - if test -z "$url" || - { - ! test -d "$sm_path"/.git && - ! test -f "$sm_path"/.git - } - then - say "-$sha1 $displaypath" - continue; - fi - if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path" - then - set_name_rev "$sm_path" "$sha1" - say " $sha1 $displaypath$revname" - else - if test -z "$cached" - then - sha1=$(sanitize_submodule_env; cd "$sm_path" && git rev-parse --verify HEAD) - fi - set_name_rev "$sm_path" "$sha1" - say "+$sha1 $displaypath$revname" - fi - - if test -n "$recursive" - then - ( - prefix="$displaypath/" - sanitize_submodule_env - wt_prefix= - cd "$sm_path" && - eval cmd_status - ) || - die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")" - fi - done + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@" } # # Sync remote urls for submodules @@ -1082,59 +1047,8 @@ cmd_sync() ;; esac done - cd_to_toplevel - { - git submodule--helper list --prefix "$wt_prefix" "$@" || - echo "#unmatched" $? - } | - while read mode sha1 stage sm_path - do - die_if_unmatched "$mode" "$sha1" - name=$(git submodule--helper name "$sm_path") - url=$(git config -f .gitmodules --get submodule."$name".url) - - # Possibly a url relative to parent - case "$url" in - ./*|../*) - # rewrite foo/bar as ../.. to find path from - # submodule work tree to superproject work tree - up_path="$(printf '%s\n' "$sm_path" | sed "s/[^/][^/]*/../g")" && - # guarantee a trailing / - up_path=${up_path%/}/ && - # path from submodule work tree to submodule origin repo - sub_origin_url=$(git submodule--helper resolve-relative-url "$url" "$up_path") && - # path from superproject work tree to submodule origin repo - super_config_url=$(git submodule--helper 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 - displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix") - say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")" - git config submodule."$name".url "$super_config_url" - - if test -e "$sm_path"/.git - then - ( - sanitize_submodule_env - 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 + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" } cmd_absorbgitdirs() @@ -1151,7 +1065,7 @@ cmd_absorbgitdirs() while test $# != 0 && test -z "$command" do case "$1" in - add | foreach | init | deinit | update | status | summary | sync | absorbgitdirs) + add | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs) command=$1 ;; -q|--quiet) @@ -1192,8 +1106,8 @@ then fi fi -# "-b branch" is accepted only by "add" -if test -n "$branch" && test "$command" != add +# "-b branch" is accepted only by "add" and "set-branch" +if test -n "$branch" && (test "$command" != add || test "$command" != set-branch) then usage fi @@ -1204,4 +1118,4 @@ then usage fi -"cmd_$command" "$@" +"cmd_$(echo $command | sed -e s/-/_/g)" "$@"