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