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