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