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