diff options
Diffstat (limited to 'git-submodule.sh')
| -rwxr-xr-x | git-submodule.sh | 340 |
1 files changed, 126 insertions, 214 deletions
diff --git a/git-submodule.sh b/git-submodule.sh index 65d62c888c..eb90f18229 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -5,11 +5,14 @@ # Copyright (c) 2007 Lars Hjemli dashless=$(basename "$0" | sed -e 's/-/ /') -USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>] +USAGE="[--quiet] [--cached] + or: $dashless [--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] deinit [-f|--force] (--all| [--] <path>...) - or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...] + or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...] + or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path> + or: $dashless [--quiet] set-url [--] <path> <newurl> or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...] or: $dashless [--quiet] foreach [--recursive] <command> or: $dashless [--quiet] sync [--recursive] [--] [<path>...] @@ -17,7 +20,6 @@ USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re OPTIONS_SPEC= SUBDIRECTORY_OK=Yes . git-sh-setup -. git-parse-remote require_work_tree wt_prefix=$(git rev-parse --show-prefix) cd_to_toplevel @@ -44,6 +46,9 @@ custom_name= depth= progress= dissociate= +single_branch= +jobs= +recommend_shallow= die_if_unmatched () { @@ -53,31 +58,6 @@ die_if_unmatched () 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 submodule--helper config submodule."$name"."$option") - fi - printf '%s' "${value:-$default}" -} - isnumber() { n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1" @@ -231,13 +211,22 @@ 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 --no-warn-embedded-repo "$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 - eval_gettextln "The following path is ignored by one of your .gitignore files: -\$sm_path -Use -f if you really want to add it." >&2 - exit 1 + 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" + then + dryerr=$(git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" 2>&1 >/dev/null) + res=$? + if test $res -ne 0 + then + echo >&2 "$dryerr" + exit $res + fi fi if test -n "$custom_name" @@ -346,7 +335,7 @@ cmd_foreach() shift done - git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} "$@" + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" } # @@ -377,7 +366,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,7 +402,7 @@ cmd_deinit() shift done - git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} "$@" + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} -- "$@" } is_tip_reachable () ( @@ -423,16 +412,18 @@ is_tip_reachable () ( test -z "$rev" ) +# usage: fetch_in_submodule <module_path> [<depth>] [<sha1>] +# Because arguments are positional, use an empty string to omit <depth> +# but include <sha1>. fetch_in_submodule () ( sanitize_submodule_env && cd "$1" && - case "$2" in - '') - git fetch ;; - *) - shift - git fetch $(get_default_remote) "$@" ;; - esac + if test $# -eq 3 + then + echo "$3" | git fetch --stdin ${2:+"$2"} + else + git fetch ${2:+"$2"} + fi ) # @@ -450,7 +441,7 @@ cmd_update() GIT_QUIET=1 ;; -v) - GIT_QUIET=0 + unset GIT_QUIET ;; --progress) progress=1 @@ -516,6 +507,12 @@ cmd_update() --jobs=*) jobs=$1 ;; + --single-branch) + single_branch="--single-branch" + ;; + --no-single-branch) + single_branch="--no-single-branch" + ;; --) shift break @@ -545,8 +542,10 @@ cmd_update() ${dissociate:+"--dissociate"} \ ${depth:+--depth "$depth"} \ ${require_init:+--require-init} \ + $single_branch \ $recommend_shallow \ $jobs \ + -- \ "$@" || echo "#unmatched" $? } | { err= @@ -554,7 +553,7 @@ cmd_update() do die_if_unmatched "$quickabort" "$sha1" - git submodule--helper ensure-core-worktree "$sm_path" + git submodule--helper ensure-core-worktree "$sm_path" || exit 1 update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update) @@ -578,7 +577,7 @@ cmd_update() fetch_in_submodule "$sm_path" $depth || die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")" fi - remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote) + remote_name=$(sanitize_submodule_env; cd "$sm_path" && git submodule--helper print-default-remote) sha1=$(sanitize_submodule_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'")" @@ -599,12 +598,12 @@ cmd_update() # is not reachable from a ref. is_tip_reachable "$sm_path" "$sha1" || fetch_in_submodule "$sm_path" $depth || - say "$(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 is_tip_reachable "$sm_path" "$sha1" || - fetch_in_submodule "$sm_path" $depth "$sha1" || + fetch_in_submodule "$sm_path" "$depth" "$sha1" || die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")" fi @@ -616,13 +615,13 @@ cmd_update() say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")" ;; rebase) - command="git rebase" + command="git rebase ${GIT_QUIET:+--quiet}" die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")" say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")" must_die_on_failure=yes ;; merge) - command="git merge" + command="git merge ${GIT_QUIET:+--quiet}" die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")" say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")" must_die_on_failure=yes @@ -691,6 +690,75 @@ cmd_update() } # +# Configures a submodule's default branch +# +# $@ = requested path +# +cmd_set_branch() { + default= + 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) + default=1 + ;; + -b|--branch) + case "$2" in '') usage ;; esac + branch=$2 + shift + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@" +} + +# +# Configures a submodule's remote url +# +# $@ = requested path, requested url +# +cmd_set_url() { + while test $# -ne 0 + do + case "$1" in + -q|--quiet) + GIT_QUIET=1 + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac + shift + done + + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper set-url ${GIT_QUIET:+--quiet} -- "$@" +} + +# # Show commit summary for submodules in index or working tree # # If '--cached' is given, show summary between index and given commit, @@ -739,163 +807,7 @@ cmd_summary() { shift done - test $summary_limit = 0 && return - - if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"}) - then - head=$rev - test $# = 0 || shift - elif test -z "$1" || test "$1" = "HEAD" - then - # before the first commit: compare with an empty tree - head=$(git hash-object -w -t tree --stdin </dev/null) - test -z "$1" || shift - else - head="HEAD" - fi - - if [ -n "$files" ] - then - test -n "$cached" && - die "$(gettext "The --cached option cannot be used with the --files option")" - diff_cmd=diff-files - head= - fi - - cd_to_toplevel - eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")" - # Get modified modules cared by user - modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" | - sane_egrep '^:([0-7]* )?160000' | - 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 - then - printf '%s\n' "$sm_path" - continue - fi - # Respect the ignore setting for --for-status. - if test -n "$for_status" - then - name=$(git submodule--helper name "$sm_path") - ignore_config=$(get_submodule_config "$name" ignore none) - 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 && - printf '%s\n' "$sm_path" - done - ) - - test -z "$modules" && return - - git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules | - sane_egrep '^:([0-7]* )?160000' | - cut -c2- | - while read -r mod_src mod_dst sha1_src sha1_dst status name - do - if test -z "$cached" && - is_zero_oid $sha1_dst - then - case "$mod_dst" in - 160000) - sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD) - ;; - 100644 | 100755 | 120000) - sha1_dst=$(git hash-object $name) - ;; - 000000) - ;; # removed - *) - # unexpected type - eval_gettextln "unexpected mode \$mod_dst" >&2 - continue ;; - esac - fi - missing_src= - missing_dst= - - test $mod_src = 160000 && - ! 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 && - missing_dst=t - - display_name=$(git submodule--helper relative-path "$name" "$wt_prefix") - - total_commits= - case "$missing_src,$missing_dst" in - t,) - errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_src")" - ;; - ,t) - errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_dst")" - ;; - t,t) - errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")" - ;; - *) - errmsg= - total_commits=$( - if test $mod_src = 160000 && test $mod_dst = 160000 - then - range="$sha1_src...$sha1_dst" - elif test $mod_src = 160000 - then - range=$sha1_src - else - range=$sha1_dst - fi - GIT_DIR="$name/.git" \ - git rev-list --first-parent $range -- | wc -l - ) - total_commits=" ($(($total_commits + 0)))" - ;; - esac - - sha1_abbr_src=$(echo $sha1_src | cut -c1-7) - sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7) - if test $status = T - then - blob="$(gettext "blob")" - submodule="$(gettext "submodule")" - if test $mod_dst = 160000 - then - echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:" - else - echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:" - fi - else - echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:" - fi - if test -n "$errmsg" - then - # Don't give error msg for modification whose dst is not submodule - # i.e. deleted or changed to blob - test $mod_dst = 160000 && echo "$errmsg" - else - if test $mod_src = 160000 && test $mod_dst = 160000 - then - limit= - test $summary_limit -gt 0 && limit="-$summary_limit" - GIT_DIR="$name/.git" \ - git log $limit --pretty='format: %m %s' \ - --first-parent $sha1_src...$sha1_dst - elif test $mod_dst = 160000 - then - GIT_DIR="$name/.git" \ - git log --pretty='format: > %s' -1 $sha1_dst - else - GIT_DIR="$name/.git" \ - git log --pretty='format: < %s' -1 $sha1_src - fi - echo - fi - echo - done + git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary ${prefix:+--prefix "$prefix"} ${files:+--files} ${cached:+--cached} ${for_status:+--for-status} ${summary_limit:+-n $summary_limit} -- "$@" } # # List all submodules, prefixed with: @@ -936,7 +848,7 @@ cmd_status() shift done - git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} "$@" + 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 @@ -969,7 +881,7 @@ cmd_sync() esac done - git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} "$@" + git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@" } cmd_absorbgitdirs() @@ -986,7 +898,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 | set-url | status | summary | sync | absorbgitdirs) command=$1 ;; -q|--quiet) @@ -1027,8 +939,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 @@ -1039,4 +951,4 @@ then usage fi -"cmd_$command" "$@" +"cmd_$(echo $command | sed -e s/-/_/g)" "$@" |
