git-submodule.shon commit Merge branch 'sb/submodule-helper' (65e1449)
   1#!/bin/sh
   2#
   3# git-submodule.sh: add, init, update or list git submodules
   4#
   5# Copyright (c) 2007 Lars Hjemli
   6
   7dashless=$(basename "$0" | sed -e 's/-/ /')
   8USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
   9   or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
  10   or: $dashless [--quiet] init [--] [<path>...]
  11   or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
  12   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--reference <repository>] [--recursive] [--] [<path>...]
  13   or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
  14   or: $dashless [--quiet] foreach [--recursive] <command>
  15   or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
  16OPTIONS_SPEC=
  17SUBDIRECTORY_OK=Yes
  18. git-sh-setup
  19. git-sh-i18n
  20. git-parse-remote
  21require_work_tree
  22wt_prefix=$(git rev-parse --show-prefix)
  23cd_to_toplevel
  24
  25command=
  26branch=
  27force=
  28reference=
  29cached=
  30recursive=
  31init=
  32files=
  33remote=
  34nofetch=
  35update=
  36prefix=
  37custom_name=
  38depth=
  39
  40# The function takes at most 2 arguments. The first argument is the
  41# URL that navigates to the submodule origin repo. When relative, this URL
  42# is relative to the superproject origin URL repo. The second up_path
  43# argument, if specified, is the relative path that navigates
  44# from the submodule working tree to the superproject working tree.
  45#
  46# The output of the function is the origin URL of the submodule.
  47#
  48# The output will either be an absolute URL or filesystem path (if the
  49# superproject origin URL is an absolute URL or filesystem path,
  50# respectively) or a relative file system path (if the superproject
  51# origin URL is a relative file system path).
  52#
  53# When the output is a relative file system path, the path is either
  54# relative to the submodule working tree, if up_path is specified, or to
  55# the superproject working tree otherwise.
  56resolve_relative_url ()
  57{
  58        remote=$(get_default_remote)
  59        remoteurl=$(git config "remote.$remote.url") ||
  60                remoteurl=$(pwd) # the repository is its own authoritative upstream
  61        url="$1"
  62        remoteurl=${remoteurl%/}
  63        sep=/
  64        up_path="$2"
  65
  66        case "$remoteurl" in
  67        *:*|/*)
  68                is_relative=
  69                ;;
  70        ./*|../*)
  71                is_relative=t
  72                ;;
  73        *)
  74                is_relative=t
  75                remoteurl="./$remoteurl"
  76                ;;
  77        esac
  78
  79        while test -n "$url"
  80        do
  81                case "$url" in
  82                ../*)
  83                        url="${url#../}"
  84                        case "$remoteurl" in
  85                        */*)
  86                                remoteurl="${remoteurl%/*}"
  87                                ;;
  88                        *:*)
  89                                remoteurl="${remoteurl%:*}"
  90                                sep=:
  91                                ;;
  92                        *)
  93                                if test -z "$is_relative" || test "." = "$remoteurl"
  94                                then
  95                                        die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
  96                                else
  97                                        remoteurl=.
  98                                fi
  99                                ;;
 100                        esac
 101                        ;;
 102                ./*)
 103                        url="${url#./}"
 104                        ;;
 105                *)
 106                        break;;
 107                esac
 108        done
 109        remoteurl="$remoteurl$sep${url%/}"
 110        echo "${is_relative:+${up_path}}${remoteurl#./}"
 111}
 112
 113# Resolve a path to be relative to another path.  This is intended for
 114# converting submodule paths when git-submodule is run in a subdirectory
 115# and only handles paths where the directory separator is '/'.
 116#
 117# The output is the first argument as a path relative to the second argument,
 118# which defaults to $wt_prefix if it is omitted.
 119relative_path ()
 120{
 121        local target curdir result
 122        target=$1
 123        curdir=${2-$wt_prefix}
 124        curdir=${curdir%/}
 125        result=
 126
 127        while test -n "$curdir"
 128        do
 129                case "$target" in
 130                "$curdir/"*)
 131                        target=${target#"$curdir"/}
 132                        break
 133                        ;;
 134                esac
 135
 136                result="${result}../"
 137                if test "$curdir" = "${curdir%/*}"
 138                then
 139                        curdir=
 140                else
 141                        curdir="${curdir%/*}"
 142                fi
 143        done
 144
 145        echo "$result$target"
 146}
 147
 148die_if_unmatched ()
 149{
 150        if test "$1" = "#unmatched"
 151        then
 152                exit 1
 153        fi
 154}
 155
 156#
 157# Print a submodule configuration setting
 158#
 159# $1 = submodule name
 160# $2 = option name
 161# $3 = default value
 162#
 163# Checks in the usual git-config places first (for overrides),
 164# otherwise it falls back on .gitmodules.  This allows you to
 165# distribute project-wide defaults in .gitmodules, while still
 166# customizing individual repositories if necessary.  If the option is
 167# not in .gitmodules either, print a default value.
 168#
 169get_submodule_config () {
 170        name="$1"
 171        option="$2"
 172        default="$3"
 173        value=$(git config submodule."$name"."$option")
 174        if test -z "$value"
 175        then
 176                value=$(git config -f .gitmodules submodule."$name"."$option")
 177        fi
 178        printf '%s' "${value:-$default}"
 179}
 180
 181isnumber()
 182{
 183        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
 184}
 185
 186#
 187# Add a new submodule to the working tree, .gitmodules and the index
 188#
 189# $@ = repo path
 190#
 191# optional branch is stored in global branch variable
 192#
 193cmd_add()
 194{
 195        # parse $args after "submodule ... add".
 196        reference_path=
 197        while test $# -ne 0
 198        do
 199                case "$1" in
 200                -b | --branch)
 201                        case "$2" in '') usage ;; esac
 202                        branch=$2
 203                        shift
 204                        ;;
 205                -f | --force)
 206                        force=$1
 207                        ;;
 208                -q|--quiet)
 209                        GIT_QUIET=1
 210                        ;;
 211                --reference)
 212                        case "$2" in '') usage ;; esac
 213                        reference_path=$2
 214                        shift
 215                        ;;
 216                --reference=*)
 217                        reference_path="${1#--reference=}"
 218                        ;;
 219                --name)
 220                        case "$2" in '') usage ;; esac
 221                        custom_name=$2
 222                        shift
 223                        ;;
 224                --depth)
 225                        case "$2" in '') usage ;; esac
 226                        depth="--depth=$2"
 227                        shift
 228                        ;;
 229                --depth=*)
 230                        depth=$1
 231                        ;;
 232                --)
 233                        shift
 234                        break
 235                        ;;
 236                -*)
 237                        usage
 238                        ;;
 239                *)
 240                        break
 241                        ;;
 242                esac
 243                shift
 244        done
 245
 246        if test -n "$reference_path"
 247        then
 248                is_absolute_path "$reference_path" ||
 249                reference_path="$wt_prefix$reference_path"
 250
 251                reference="--reference=$reference_path"
 252        fi
 253
 254        repo=$1
 255        sm_path=$2
 256
 257        if test -z "$sm_path"; then
 258                sm_path=$(printf '%s\n' "$repo" |
 259                        sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
 260        fi
 261
 262        if test -z "$repo" || test -z "$sm_path"; then
 263                usage
 264        fi
 265
 266        is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
 267
 268        # assure repo is absolute or relative to parent
 269        case "$repo" in
 270        ./*|../*)
 271                test -z "$wt_prefix" ||
 272                die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
 273
 274                # dereference source url relative to parent's url
 275                realrepo=$(resolve_relative_url "$repo") || exit
 276                ;;
 277        *:*|/*)
 278                # absolute url
 279                realrepo=$repo
 280                ;;
 281        *)
 282                die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
 283        ;;
 284        esac
 285
 286        # normalize path:
 287        # multiple //; leading ./; /./; /../; trailing /
 288        sm_path=$(printf '%s/\n' "$sm_path" |
 289                sed -e '
 290                        s|//*|/|g
 291                        s|^\(\./\)*||
 292                        s|/\(\./\)*|/|g
 293                        :start
 294                        s|\([^/]*\)/\.\./||
 295                        tstart
 296                        s|/*$||
 297                ')
 298        git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
 299        die "$(eval_gettext "'\$sm_path' already exists in the index")"
 300
 301        if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
 302        then
 303                eval_gettextln "The following path is ignored by one of your .gitignore files:
 304\$sm_path
 305Use -f if you really want to add it." >&2
 306                exit 1
 307        fi
 308
 309        if test -n "$custom_name"
 310        then
 311                sm_name="$custom_name"
 312        else
 313                sm_name="$sm_path"
 314        fi
 315
 316        # perhaps the path exists and is already a git repo, else clone it
 317        if test -e "$sm_path"
 318        then
 319                if test -d "$sm_path"/.git || test -f "$sm_path"/.git
 320                then
 321                        eval_gettextln "Adding existing repo at '\$sm_path' to the index"
 322                else
 323                        die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")"
 324                fi
 325
 326        else
 327                if test -d ".git/modules/$sm_name"
 328                then
 329                        if test -z "$force"
 330                        then
 331                                echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")"
 332                                GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^,"  ", -e s,' (fetch)',, >&2
 333                                echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")"
 334                                echo >&2 "  $realrepo"
 335                                echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")"
 336                                die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")"
 337                        else
 338                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 339                        fi
 340                fi
 341                git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
 342                (
 343                        clear_local_git_env
 344                        cd "$sm_path" &&
 345                        # ash fails to wordsplit ${branch:+-b "$branch"...}
 346                        case "$branch" in
 347                        '') git checkout -f -q ;;
 348                        ?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
 349                        esac
 350                ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
 351        fi
 352        git config submodule."$sm_name".url "$realrepo"
 353
 354        git add $force "$sm_path" ||
 355        die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
 356
 357        git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
 358        git config -f .gitmodules submodule."$sm_name".url "$repo" &&
 359        if test -n "$branch"
 360        then
 361                git config -f .gitmodules submodule."$sm_name".branch "$branch"
 362        fi &&
 363        git add --force .gitmodules ||
 364        die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 365}
 366
 367#
 368# Execute an arbitrary command sequence in each checked out
 369# submodule
 370#
 371# $@ = command to execute
 372#
 373cmd_foreach()
 374{
 375        # parse $args after "submodule ... foreach".
 376        while test $# -ne 0
 377        do
 378                case "$1" in
 379                -q|--quiet)
 380                        GIT_QUIET=1
 381                        ;;
 382                --recursive)
 383                        recursive=1
 384                        ;;
 385                -*)
 386                        usage
 387                        ;;
 388                *)
 389                        break
 390                        ;;
 391                esac
 392                shift
 393        done
 394
 395        toplevel=$(pwd)
 396
 397        # dup stdin so that it can be restored when running the external
 398        # command in the subshell (and a recursive call to this function)
 399        exec 3<&0
 400
 401        git submodule--helper list --prefix "$wt_prefix"|
 402        while read mode sha1 stage sm_path
 403        do
 404                die_if_unmatched "$mode"
 405                if test -e "$sm_path"/.git
 406                then
 407                        displaypath=$(relative_path "$sm_path")
 408                        say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
 409                        name=$(git submodule--helper name "$sm_path")
 410                        (
 411                                prefix="$prefix$sm_path/"
 412                                clear_local_git_env
 413                                cd "$sm_path" &&
 414                                sm_path=$(relative_path "$sm_path") &&
 415                                # we make $path available to scripts ...
 416                                path=$sm_path &&
 417                                if test $# -eq 1
 418                                then
 419                                        eval "$1"
 420                                else
 421                                        "$@"
 422                                fi &&
 423                                if test -n "$recursive"
 424                                then
 425                                        cmd_foreach "--recursive" "$@"
 426                                fi
 427                        ) <&3 3<&- ||
 428                        die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
 429                fi
 430        done
 431}
 432
 433#
 434# Register submodules in .git/config
 435#
 436# $@ = requested paths (default to all)
 437#
 438cmd_init()
 439{
 440        # parse $args after "submodule ... init".
 441        while test $# -ne 0
 442        do
 443                case "$1" in
 444                -q|--quiet)
 445                        GIT_QUIET=1
 446                        ;;
 447                --)
 448                        shift
 449                        break
 450                        ;;
 451                -*)
 452                        usage
 453                        ;;
 454                *)
 455                        break
 456                        ;;
 457                esac
 458                shift
 459        done
 460
 461        git submodule--helper list --prefix "$wt_prefix" "$@" |
 462        while read mode sha1 stage sm_path
 463        do
 464                die_if_unmatched "$mode"
 465                name=$(git submodule--helper name "$sm_path") || exit
 466
 467                displaypath=$(relative_path "$sm_path")
 468
 469                # Copy url setting when it is not set yet
 470                if test -z "$(git config "submodule.$name.url")"
 471                then
 472                        url=$(git config -f .gitmodules submodule."$name".url)
 473                        test -z "$url" &&
 474                        die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
 475
 476                        # Possibly a url relative to parent
 477                        case "$url" in
 478                        ./*|../*)
 479                                url=$(resolve_relative_url "$url") || exit
 480                                ;;
 481                        esac
 482                        git config submodule."$name".url "$url" ||
 483                        die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
 484
 485                        say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
 486                fi
 487
 488                # Copy "update" setting when it is not set yet
 489                if upd="$(git config -f .gitmodules submodule."$name".update)" &&
 490                   test -n "$upd" &&
 491                   test -z "$(git config submodule."$name".update)"
 492                then
 493                        case "$upd" in
 494                        checkout | rebase | merge | none)
 495                                ;; # known modes of updating
 496                        *)
 497                                echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
 498                                upd=none
 499                                ;;
 500                        esac
 501                        git config submodule."$name".update "$upd" ||
 502                        die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 503                fi
 504        done
 505}
 506
 507#
 508# Unregister submodules from .git/config and remove their work tree
 509#
 510# $@ = requested paths (use '.' to deinit all submodules)
 511#
 512cmd_deinit()
 513{
 514        # parse $args after "submodule ... deinit".
 515        while test $# -ne 0
 516        do
 517                case "$1" in
 518                -f|--force)
 519                        force=$1
 520                        ;;
 521                -q|--quiet)
 522                        GIT_QUIET=1
 523                        ;;
 524                --)
 525                        shift
 526                        break
 527                        ;;
 528                -*)
 529                        usage
 530                        ;;
 531                *)
 532                        break
 533                        ;;
 534                esac
 535                shift
 536        done
 537
 538        if test $# = 0
 539        then
 540                die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 541        fi
 542
 543        git submodule--helper list --prefix "$wt_prefix" "$@" |
 544        while read mode sha1 stage sm_path
 545        do
 546                die_if_unmatched "$mode"
 547                name=$(git submodule--helper name "$sm_path") || exit
 548
 549                displaypath=$(relative_path "$sm_path")
 550
 551                # Remove the submodule work tree (unless the user already did it)
 552                if test -d "$sm_path"
 553                then
 554                        # Protect submodules containing a .git directory
 555                        if test -d "$sm_path/.git"
 556                        then
 557                                echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
 558                                die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
 559                        fi
 560
 561                        if test -z "$force"
 562                        then
 563                                git rm -qn "$sm_path" ||
 564                                die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
 565                        fi
 566                        rm -rf "$sm_path" &&
 567                        say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
 568                        say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
 569                fi
 570
 571                mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
 572
 573                # Remove the .git/config entries (unless the user already did it)
 574                if test -n "$(git config --get-regexp submodule."$name\.")"
 575                then
 576                        # Remove the whole section so we have a clean state when
 577                        # the user later decides to init this submodule again
 578                        url=$(git config submodule."$name".url)
 579                        git config --remove-section submodule."$name" 2>/dev/null &&
 580                        say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
 581                fi
 582        done
 583}
 584
 585#
 586# Update each submodule path to correct revision, using clone and checkout as needed
 587#
 588# $@ = requested paths (default to all)
 589#
 590cmd_update()
 591{
 592        # parse $args after "submodule ... update".
 593        while test $# -ne 0
 594        do
 595                case "$1" in
 596                -q|--quiet)
 597                        GIT_QUIET=1
 598                        ;;
 599                -i|--init)
 600                        init=1
 601                        ;;
 602                --remote)
 603                        remote=1
 604                        ;;
 605                -N|--no-fetch)
 606                        nofetch=1
 607                        ;;
 608                -f|--force)
 609                        force=$1
 610                        ;;
 611                -r|--rebase)
 612                        update="rebase"
 613                        ;;
 614                --reference)
 615                        case "$2" in '') usage ;; esac
 616                        reference="--reference=$2"
 617                        shift
 618                        ;;
 619                --reference=*)
 620                        reference="$1"
 621                        ;;
 622                -m|--merge)
 623                        update="merge"
 624                        ;;
 625                --recursive)
 626                        recursive=1
 627                        ;;
 628                --checkout)
 629                        update="checkout"
 630                        ;;
 631                --depth)
 632                        case "$2" in '') usage ;; esac
 633                        depth="--depth=$2"
 634                        shift
 635                        ;;
 636                --depth=*)
 637                        depth=$1
 638                        ;;
 639                --)
 640                        shift
 641                        break
 642                        ;;
 643                -*)
 644                        usage
 645                        ;;
 646                *)
 647                        break
 648                        ;;
 649                esac
 650                shift
 651        done
 652
 653        if test -n "$init"
 654        then
 655                cmd_init "--" "$@" || return
 656        fi
 657
 658        cloned_modules=
 659        git submodule--helper list --prefix "$wt_prefix" "$@" | {
 660        err=
 661        while read mode sha1 stage sm_path
 662        do
 663                die_if_unmatched "$mode"
 664                if test "$stage" = U
 665                then
 666                        echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 667                        continue
 668                fi
 669                name=$(git submodule--helper name "$sm_path") || exit
 670                url=$(git config submodule."$name".url)
 671                branch=$(get_submodule_config "$name" branch master)
 672                if ! test -z "$update"
 673                then
 674                        update_module=$update
 675                else
 676                        update_module=$(git config submodule."$name".update)
 677                        if test -z "$update_module"
 678                        then
 679                                update_module="checkout"
 680                        fi
 681                fi
 682
 683                displaypath=$(relative_path "$prefix$sm_path")
 684
 685                if test "$update_module" = "none"
 686                then
 687                        echo "Skipping submodule '$displaypath'"
 688                        continue
 689                fi
 690
 691                if test -z "$url"
 692                then
 693                        # Only mention uninitialized submodules when its
 694                        # path have been specified
 695                        test "$#" != "0" &&
 696                        say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 697Maybe you want to use 'update --init'?")"
 698                        continue
 699                fi
 700
 701                if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
 702                then
 703                        git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
 704                        cloned_modules="$cloned_modules;$name"
 705                        subsha1=
 706                else
 707                        subsha1=$(clear_local_git_env; cd "$sm_path" &&
 708                                git rev-parse --verify HEAD) ||
 709                        die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 710                fi
 711
 712                if test -n "$remote"
 713                then
 714                        if test -z "$nofetch"
 715                        then
 716                                # Fetch remote before determining tracking $sha1
 717                                (clear_local_git_env; cd "$sm_path" && git-fetch) ||
 718                                die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
 719                        fi
 720                        remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
 721                        sha1=$(clear_local_git_env; cd "$sm_path" &&
 722                                git rev-parse --verify "${remote_name}/${branch}") ||
 723                        die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
 724                fi
 725
 726                if test "$subsha1" != "$sha1" || test -n "$force"
 727                then
 728                        subforce=$force
 729                        # If we don't already have a -f flag and the submodule has never been checked out
 730                        if test -z "$subsha1" && test -z "$force"
 731                        then
 732                                subforce="-f"
 733                        fi
 734
 735                        if test -z "$nofetch"
 736                        then
 737                                # Run fetch only if $sha1 isn't present or it
 738                                # is not reachable from a ref.
 739                                (clear_local_git_env; cd "$sm_path" &&
 740                                        ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
 741                                         test -z "$rev") || git-fetch)) ||
 742                                die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
 743                        fi
 744
 745                        # Is this something we just cloned?
 746                        case ";$cloned_modules;" in
 747                        *";$name;"*)
 748                                # then there is no local change to integrate
 749                                update_module=checkout ;;
 750                        esac
 751
 752                        must_die_on_failure=
 753                        case "$update_module" in
 754                        checkout)
 755                                command="git checkout $subforce -q"
 756                                die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
 757                                say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 758                                ;;
 759                        rebase)
 760                                command="git rebase"
 761                                die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
 762                                say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
 763                                must_die_on_failure=yes
 764                                ;;
 765                        merge)
 766                                command="git merge"
 767                                die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
 768                                say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
 769                                must_die_on_failure=yes
 770                                ;;
 771                        !*)
 772                                command="${update_module#!}"
 773                                die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
 774                                say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
 775                                must_die_on_failure=yes
 776                                ;;
 777                        *)
 778                                die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 779                        esac
 780
 781                        if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
 782                        then
 783                                say "$say_msg"
 784                        elif test -n "$must_die_on_failure"
 785                        then
 786                                die_with_status 2 "$die_msg"
 787                        else
 788                                err="${err};$die_msg"
 789                                continue
 790                        fi
 791                fi
 792
 793                if test -n "$recursive"
 794                then
 795                        (
 796                                prefix="$prefix$sm_path/"
 797                                clear_local_git_env
 798                                cd "$sm_path" &&
 799                                eval cmd_update
 800                        )
 801                        res=$?
 802                        if test $res -gt 0
 803                        then
 804                                die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
 805                                if test $res -eq 1
 806                                then
 807                                        err="${err};$die_msg"
 808                                        continue
 809                                else
 810                                        die_with_status $res "$die_msg"
 811                                fi
 812                        fi
 813                fi
 814        done
 815
 816        if test -n "$err"
 817        then
 818                OIFS=$IFS
 819                IFS=';'
 820                for e in $err
 821                do
 822                        if test -n "$e"
 823                        then
 824                                echo >&2 "$e"
 825                        fi
 826                done
 827                IFS=$OIFS
 828                exit 1
 829        fi
 830        }
 831}
 832
 833set_name_rev () {
 834        revname=$( (
 835                clear_local_git_env
 836                cd "$1" && {
 837                        git describe "$2" 2>/dev/null ||
 838                        git describe --tags "$2" 2>/dev/null ||
 839                        git describe --contains "$2" 2>/dev/null ||
 840                        git describe --all --always "$2"
 841                }
 842        ) )
 843        test -z "$revname" || revname=" ($revname)"
 844}
 845#
 846# Show commit summary for submodules in index or working tree
 847#
 848# If '--cached' is given, show summary between index and given commit,
 849# or between working tree and given commit
 850#
 851# $@ = [commit (default 'HEAD'),] requested paths (default all)
 852#
 853cmd_summary() {
 854        summary_limit=-1
 855        for_status=
 856        diff_cmd=diff-index
 857
 858        # parse $args after "submodule ... summary".
 859        while test $# -ne 0
 860        do
 861                case "$1" in
 862                --cached)
 863                        cached="$1"
 864                        ;;
 865                --files)
 866                        files="$1"
 867                        ;;
 868                --for-status)
 869                        for_status="$1"
 870                        ;;
 871                -n|--summary-limit)
 872                        summary_limit="$2"
 873                        isnumber "$summary_limit" || usage
 874                        shift
 875                        ;;
 876                --summary-limit=*)
 877                        summary_limit="${1#--summary-limit=}"
 878                        isnumber "$summary_limit" || usage
 879                        ;;
 880                --)
 881                        shift
 882                        break
 883                        ;;
 884                -*)
 885                        usage
 886                        ;;
 887                *)
 888                        break
 889                        ;;
 890                esac
 891                shift
 892        done
 893
 894        test $summary_limit = 0 && return
 895
 896        if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
 897        then
 898                head=$rev
 899                test $# = 0 || shift
 900        elif test -z "$1" || test "$1" = "HEAD"
 901        then
 902                # before the first commit: compare with an empty tree
 903                head=$(git hash-object -w -t tree --stdin </dev/null)
 904                test -z "$1" || shift
 905        else
 906                head="HEAD"
 907        fi
 908
 909        if [ -n "$files" ]
 910        then
 911                test -n "$cached" &&
 912                die "$(gettext "The --cached option cannot be used with the --files option")"
 913                diff_cmd=diff-files
 914                head=
 915        fi
 916
 917        cd_to_toplevel
 918        eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 919        # Get modified modules cared by user
 920        modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
 921                sane_egrep '^:([0-7]* )?160000' |
 922                while read mod_src mod_dst sha1_src sha1_dst status sm_path
 923                do
 924                        # Always show modules deleted or type-changed (blob<->module)
 925                        if test "$status" = D || test "$status" = T
 926                        then
 927                                printf '%s\n' "$sm_path"
 928                                continue
 929                        fi
 930                        # Respect the ignore setting for --for-status.
 931                        if test -n "$for_status"
 932                        then
 933                                name=$(git submodule--helper name "$sm_path")
 934                                ignore_config=$(get_submodule_config "$name" ignore none)
 935                                test $status != A && test $ignore_config = all && continue
 936                        fi
 937                        # Also show added or modified modules which are checked out
 938                        GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
 939                        printf '%s\n' "$sm_path"
 940                done
 941        )
 942
 943        test -z "$modules" && return
 944
 945        git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
 946        sane_egrep '^:([0-7]* )?160000' |
 947        cut -c2- |
 948        while read mod_src mod_dst sha1_src sha1_dst status name
 949        do
 950                if test -z "$cached" &&
 951                        test $sha1_dst = 0000000000000000000000000000000000000000
 952                then
 953                        case "$mod_dst" in
 954                        160000)
 955                                sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
 956                                ;;
 957                        100644 | 100755 | 120000)
 958                                sha1_dst=$(git hash-object $name)
 959                                ;;
 960                        000000)
 961                                ;; # removed
 962                        *)
 963                                # unexpected type
 964                                eval_gettextln "unexpected mode \$mod_dst" >&2
 965                                continue ;;
 966                        esac
 967                fi
 968                missing_src=
 969                missing_dst=
 970
 971                test $mod_src = 160000 &&
 972                ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
 973                missing_src=t
 974
 975                test $mod_dst = 160000 &&
 976                ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
 977                missing_dst=t
 978
 979                display_name=$(relative_path "$name")
 980
 981                total_commits=
 982                case "$missing_src,$missing_dst" in
 983                t,)
 984                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_src")"
 985                        ;;
 986                ,t)
 987                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_dst")"
 988                        ;;
 989                t,t)
 990                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
 991                        ;;
 992                *)
 993                        errmsg=
 994                        total_commits=$(
 995                        if test $mod_src = 160000 && test $mod_dst = 160000
 996                        then
 997                                range="$sha1_src...$sha1_dst"
 998                        elif test $mod_src = 160000
 999                        then
1000                                range=$sha1_src
1001                        else
1002                                range=$sha1_dst
1003                        fi
1004                        GIT_DIR="$name/.git" \
1005                        git rev-list --first-parent $range -- | wc -l
1006                        )
1007                        total_commits=" ($(($total_commits + 0)))"
1008                        ;;
1009                esac
1010
1011                sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
1012                sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
1013                if test $status = T
1014                then
1015                        blob="$(gettext "blob")"
1016                        submodule="$(gettext "submodule")"
1017                        if test $mod_dst = 160000
1018                        then
1019                                echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
1020                        else
1021                                echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
1022                        fi
1023                else
1024                        echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
1025                fi
1026                if test -n "$errmsg"
1027                then
1028                        # Don't give error msg for modification whose dst is not submodule
1029                        # i.e. deleted or changed to blob
1030                        test $mod_dst = 160000 && echo "$errmsg"
1031                else
1032                        if test $mod_src = 160000 && test $mod_dst = 160000
1033                        then
1034                                limit=
1035                                test $summary_limit -gt 0 && limit="-$summary_limit"
1036                                GIT_DIR="$name/.git" \
1037                                git log $limit --pretty='format:  %m %s' \
1038                                --first-parent $sha1_src...$sha1_dst
1039                        elif test $mod_dst = 160000
1040                        then
1041                                GIT_DIR="$name/.git" \
1042                                git log --pretty='format:  > %s' -1 $sha1_dst
1043                        else
1044                                GIT_DIR="$name/.git" \
1045                                git log --pretty='format:  < %s' -1 $sha1_src
1046                        fi
1047                        echo
1048                fi
1049                echo
1050        done
1051}
1052#
1053# List all submodules, prefixed with:
1054#  - submodule not initialized
1055#  + different revision checked out
1056#
1057# If --cached was specified the revision in the index will be printed
1058# instead of the currently checked out revision.
1059#
1060# $@ = requested paths (default to all)
1061#
1062cmd_status()
1063{
1064        # parse $args after "submodule ... status".
1065        while test $# -ne 0
1066        do
1067                case "$1" in
1068                -q|--quiet)
1069                        GIT_QUIET=1
1070                        ;;
1071                --cached)
1072                        cached=1
1073                        ;;
1074                --recursive)
1075                        recursive=1
1076                        ;;
1077                --)
1078                        shift
1079                        break
1080                        ;;
1081                -*)
1082                        usage
1083                        ;;
1084                *)
1085                        break
1086                        ;;
1087                esac
1088                shift
1089        done
1090
1091        git submodule--helper list --prefix "$wt_prefix" "$@" |
1092        while read mode sha1 stage sm_path
1093        do
1094                die_if_unmatched "$mode"
1095                name=$(git submodule--helper name "$sm_path") || exit
1096                url=$(git config submodule."$name".url)
1097                displaypath=$(relative_path "$prefix$sm_path")
1098                if test "$stage" = U
1099                then
1100                        say "U$sha1 $displaypath"
1101                        continue
1102                fi
1103                if test -z "$url" ||
1104                {
1105                        ! test -d "$sm_path"/.git &&
1106                        ! test -f "$sm_path"/.git
1107                }
1108                then
1109                        say "-$sha1 $displaypath"
1110                        continue;
1111                fi
1112                if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
1113                then
1114                        set_name_rev "$sm_path" "$sha1"
1115                        say " $sha1 $displaypath$revname"
1116                else
1117                        if test -z "$cached"
1118                        then
1119                                sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
1120                        fi
1121                        set_name_rev "$sm_path" "$sha1"
1122                        say "+$sha1 $displaypath$revname"
1123                fi
1124
1125                if test -n "$recursive"
1126                then
1127                        (
1128                                prefix="$displaypath/"
1129                                clear_local_git_env
1130                                cd "$sm_path" &&
1131                                eval cmd_status
1132                        ) ||
1133                        die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
1134                fi
1135        done
1136}
1137#
1138# Sync remote urls for submodules
1139# This makes the value for remote.$remote.url match the value
1140# specified in .gitmodules.
1141#
1142cmd_sync()
1143{
1144        while test $# -ne 0
1145        do
1146                case "$1" in
1147                -q|--quiet)
1148                        GIT_QUIET=1
1149                        shift
1150                        ;;
1151                --recursive)
1152                        recursive=1
1153                        shift
1154                        ;;
1155                --)
1156                        shift
1157                        break
1158                        ;;
1159                -*)
1160                        usage
1161                        ;;
1162                *)
1163                        break
1164                        ;;
1165                esac
1166        done
1167        cd_to_toplevel
1168        git submodule--helper list --prefix "$wt_prefix" "$@" |
1169        while read mode sha1 stage sm_path
1170        do
1171                die_if_unmatched "$mode"
1172                name=$(git submodule--helper name "$sm_path")
1173                url=$(git config -f .gitmodules --get submodule."$name".url)
1174
1175                # Possibly a url relative to parent
1176                case "$url" in
1177                ./*|../*)
1178                        # rewrite foo/bar as ../.. to find path from
1179                        # submodule work tree to superproject work tree
1180                        up_path="$(printf '%s\n' "$sm_path" | sed "s/[^/][^/]*/../g")" &&
1181                        # guarantee a trailing /
1182                        up_path=${up_path%/}/ &&
1183                        # path from submodule work tree to submodule origin repo
1184                        sub_origin_url=$(resolve_relative_url "$url" "$up_path") &&
1185                        # path from superproject work tree to submodule origin repo
1186                        super_config_url=$(resolve_relative_url "$url") || exit
1187                        ;;
1188                *)
1189                        sub_origin_url="$url"
1190                        super_config_url="$url"
1191                        ;;
1192                esac
1193
1194                if git config "submodule.$name.url" >/dev/null 2>/dev/null
1195                then
1196                        displaypath=$(relative_path "$prefix$sm_path")
1197                        say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
1198                        git config submodule."$name".url "$super_config_url"
1199
1200                        if test -e "$sm_path"/.git
1201                        then
1202                        (
1203                                clear_local_git_env
1204                                cd "$sm_path"
1205                                remote=$(get_default_remote)
1206                                git config remote."$remote".url "$sub_origin_url"
1207
1208                                if test -n "$recursive"
1209                                then
1210                                        prefix="$prefix$sm_path/"
1211                                        eval cmd_sync
1212                                fi
1213                        )
1214                        fi
1215                fi
1216        done
1217}
1218
1219# This loop parses the command line arguments to find the
1220# subcommand name to dispatch.  Parsing of the subcommand specific
1221# options are primarily done by the subcommand implementations.
1222# Subcommand specific options such as --branch and --cached are
1223# parsed here as well, for backward compatibility.
1224
1225while test $# != 0 && test -z "$command"
1226do
1227        case "$1" in
1228        add | foreach | init | deinit | update | status | summary | sync)
1229                command=$1
1230                ;;
1231        -q|--quiet)
1232                GIT_QUIET=1
1233                ;;
1234        -b|--branch)
1235                case "$2" in
1236                '')
1237                        usage
1238                        ;;
1239                esac
1240                branch="$2"; shift
1241                ;;
1242        --cached)
1243                cached="$1"
1244                ;;
1245        --)
1246                break
1247                ;;
1248        -*)
1249                usage
1250                ;;
1251        *)
1252                break
1253                ;;
1254        esac
1255        shift
1256done
1257
1258# No command word defaults to "status"
1259if test -z "$command"
1260then
1261    if test $# = 0
1262    then
1263        command=status
1264    else
1265        usage
1266    fi
1267fi
1268
1269# "-b branch" is accepted only by "add"
1270if test -n "$branch" && test "$command" != add
1271then
1272        usage
1273fi
1274
1275# "--cached" is accepted only by "status" and "summary"
1276if test -n "$cached" && test "$command" != status && test "$command" != summary
1277then
1278        usage
1279fi
1280
1281"cmd_$command" "$@"