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