626a746f7c89e915115bd70a9975576f5184d9b6
   1#!/bin/sh
   2#
   3# git-submodule.sh: add, init, update or list git submodules
   4#
   5# Copyright (c) 2007 Lars Hjemli
   6
   7dashless=$(basename "$0" | sed -e 's/-/ /')
   8USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
   9   or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
  10   or: $dashless [--quiet] init [--] [<path>...]
  11   or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
  12   or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
  13   or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
  14   or: $dashless [--quiet] foreach [--recursive] <command>
  15   or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
  16OPTIONS_SPEC=
  17SUBDIRECTORY_OK=Yes
  18. git-sh-setup
  19. git-sh-i18n
  20. git-parse-remote
  21require_work_tree
  22wt_prefix=$(git rev-parse --show-prefix)
  23cd_to_toplevel
  24
  25command=
  26branch=
  27force=
  28reference=
  29cached=
  30recursive=
  31init=
  32files=
  33remote=
  34nofetch=
  35update=
  36prefix=
  37custom_name=
  38depth=
  39
  40# The function takes at most 2 arguments. The first argument is the
  41# URL that navigates to the submodule origin repo. When relative, this URL
  42# is relative to the superproject origin URL repo. The second up_path
  43# argument, if specified, is the relative path that navigates
  44# from the submodule working tree to the superproject working tree.
  45#
  46# The output of the function is the origin URL of the submodule.
  47#
  48# The output will either be an absolute URL or filesystem path (if the
  49# superproject origin URL is an absolute URL or filesystem path,
  50# respectively) or a relative file system path (if the superproject
  51# origin URL is a relative file system path).
  52#
  53# When the output is a relative file system path, the path is either
  54# relative to the submodule working tree, if up_path is specified, or to
  55# the superproject working tree otherwise.
  56resolve_relative_url ()
  57{
  58        remote=$(get_default_remote)
  59        remoteurl=$(git config "remote.$remote.url") ||
  60                remoteurl=$(pwd) # the repository is its own authoritative upstream
  61        url="$1"
  62        remoteurl=${remoteurl%/}
  63        sep=/
  64        up_path="$2"
  65
  66        case "$remoteurl" in
  67        *:*|/*)
  68                is_relative=
  69                ;;
  70        ./*|../*)
  71                is_relative=t
  72                ;;
  73        *)
  74                is_relative=t
  75                remoteurl="./$remoteurl"
  76                ;;
  77        esac
  78
  79        while test -n "$url"
  80        do
  81                case "$url" in
  82                ../*)
  83                        url="${url#../}"
  84                        case "$remoteurl" in
  85                        */*)
  86                                remoteurl="${remoteurl%/*}"
  87                                ;;
  88                        *:*)
  89                                remoteurl="${remoteurl%:*}"
  90                                sep=:
  91                                ;;
  92                        *)
  93                                if test -z "$is_relative" || test "." = "$remoteurl"
  94                                then
  95                                        die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
  96                                else
  97                                        remoteurl=.
  98                                fi
  99                                ;;
 100                        esac
 101                        ;;
 102                ./*)
 103                        url="${url#./}"
 104                        ;;
 105                *)
 106                        break;;
 107                esac
 108        done
 109        remoteurl="$remoteurl$sep${url%/}"
 110        echo "${is_relative:+${up_path}}${remoteurl#./}"
 111}
 112
 113# Resolve a path to be relative to another path.  This is intended for
 114# converting submodule paths when git-submodule is run in a subdirectory
 115# and only handles paths where the directory separator is '/'.
 116#
 117# The output is the first argument as a path relative to the second argument,
 118# which defaults to $wt_prefix if it is omitted.
 119relative_path ()
 120{
 121        local target curdir result
 122        target=$1
 123        curdir=${2-$wt_prefix}
 124        curdir=${curdir%/}
 125        result=
 126
 127        while test -n "$curdir"
 128        do
 129                case "$target" in
 130                "$curdir/"*)
 131                        target=${target#"$curdir"/}
 132                        break
 133                        ;;
 134                esac
 135
 136                result="${result}../"
 137                if test "$curdir" = "${curdir%/*}"
 138                then
 139                        curdir=
 140                else
 141                        curdir="${curdir%/*}"
 142                fi
 143        done
 144
 145        echo "$result$target"
 146}
 147
 148#
 149# Get submodule info for registered submodules
 150# $@ = path to limit submodule list
 151#
 152module_list()
 153{
 154        eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 155        (
 156                git ls-files -z --error-unmatch --stage -- "$@" ||
 157                echo "unmatched pathspec exists"
 158        ) |
 159        perl -e '
 160        my %unmerged = ();
 161        my ($null_sha1) = ("0" x 40);
 162        my @out = ();
 163        my $unmatched = 0;
 164        $/ = "\0";
 165        while (<STDIN>) {
 166                if (/^unmatched pathspec/) {
 167                        $unmatched = 1;
 168                        next;
 169                }
 170                chomp;
 171                my ($mode, $sha1, $stage, $path) =
 172                        /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
 173                next unless $mode eq "160000";
 174                if ($stage ne "0") {
 175                        if (!$unmerged{$path}++) {
 176                                push @out, "$mode $null_sha1 U\t$path\n";
 177                        }
 178                        next;
 179                }
 180                push @out, "$_\n";
 181        }
 182        if ($unmatched) {
 183                print "#unmatched\n";
 184        } else {
 185                print for (@out);
 186        }
 187        '
 188}
 189
 190die_if_unmatched ()
 191{
 192        if test "$1" = "#unmatched"
 193        then
 194                exit 1
 195        fi
 196}
 197
 198#
 199# Print a submodule configuration setting
 200#
 201# $1 = submodule name
 202# $2 = option name
 203# $3 = default value
 204#
 205# Checks in the usual git-config places first (for overrides),
 206# otherwise it falls back on .gitmodules.  This allows you to
 207# distribute project-wide defaults in .gitmodules, while still
 208# customizing individual repositories if necessary.  If the option is
 209# not in .gitmodules either, print a default value.
 210#
 211get_submodule_config () {
 212        name="$1"
 213        option="$2"
 214        default="$3"
 215        value=$(git config submodule."$name"."$option")
 216        if test -z "$value"
 217        then
 218                value=$(git config -f .gitmodules submodule."$name"."$option")
 219        fi
 220        printf '%s' "${value:-$default}"
 221}
 222
 223
 224#
 225# Map submodule path to submodule name
 226#
 227# $1 = path
 228#
 229module_name()
 230{
 231        # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
 232        sm_path="$1"
 233        re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
 234        name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
 235                sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
 236        test -z "$name" &&
 237        die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
 238        echo "$name"
 239}
 240
 241#
 242# Clone a submodule
 243#
 244# $1 = submodule path
 245# $2 = submodule name
 246# $3 = URL to clone
 247# $4 = reference repository to reuse (empty for independent)
 248# $5 = depth argument for shallow clones (empty for deep)
 249# $6 = (remote-tracking) starting point for the local branch (empty for HEAD)
 250# $7 = local branch to create (empty for a detached HEAD, unless $6 is
 251#      also empty, in which case the local branch is left unchanged)
 252#
 253# Prior to calling, cmd_update checks that a possibly existing
 254# path is not a git repository.
 255# Likewise, cmd_add checks that path does not exist at all,
 256# since it is the location of a new submodule.
 257#
 258module_clone()
 259{
 260        sm_path=$1
 261        name=$2
 262        url=$3
 263        reference="$4"
 264        depth="$5"
 265        start_point="$6"
 266        local_branch="$7"
 267        quiet=
 268        if test -n "$GIT_QUIET"
 269        then
 270                quiet=-q
 271        fi
 272
 273        gitdir=
 274        gitdir_base=
 275        base_name=$(dirname "$name")
 276
 277        gitdir=$(git rev-parse --git-dir)
 278        gitdir_base="$gitdir/modules/$base_name"
 279        gitdir="$gitdir/modules/$name"
 280
 281        if test -d "$gitdir"
 282        then
 283                mkdir -p "$sm_path"
 284                rm -f "$gitdir/index"
 285        else
 286                mkdir -p "$gitdir_base"
 287                (
 288                        clear_local_git_env
 289                        git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
 290                                --separate-git-dir "$gitdir" "$url" "$sm_path"
 291                ) ||
 292                die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
 293        fi
 294
 295        # We already are at the root of the work tree but cd_to_toplevel will
 296        # resolve any symlinks that might be present in $PWD
 297        a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
 298        b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
 299        # normalize Windows-style absolute paths to POSIX-style absolute paths
 300        case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac
 301        case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac
 302        # Remove all common leading directories after a sanity check
 303        if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
 304                die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
 305        fi
 306        while test "${a%%/*}" = "${b%%/*}"
 307        do
 308                a=${a#*/}
 309                b=${b#*/}
 310        done
 311        # Now chop off the trailing '/'s that were added in the beginning
 312        a=${a%/}
 313        b=${b%/}
 314
 315        # Turn each leading "*/" component into "../"
 316        rel=$(echo $b | sed -e 's|[^/][^/]*|..|g')
 317        echo "gitdir: $rel/$a" >"$sm_path/.git"
 318
 319        rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
 320        (
 321                clear_local_git_env
 322                cd "$sm_path" &&
 323                GIT_WORK_TREE=. git config core.worktree "$rel/$b" &&
 324                # ash fails to wordsplit ${local_branch:+-B "$local_branch"...}
 325                case "$local_branch" in
 326                '') git checkout -f -q ${start_point:+"$start_point"} ;;
 327                ?*) git checkout -f -q -B "$local_branch" ${start_point:+"$start_point"} ;;
 328                esac
 329        ) || die "$(eval_gettext "Unable to setup cloned submodule '\$sm_path'")"
 330}
 331
 332isnumber()
 333{
 334        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
 335}
 336
 337#
 338# Add a new submodule to the working tree, .gitmodules and the index
 339#
 340# $@ = repo path
 341#
 342# optional branch is stored in global branch variable
 343#
 344cmd_add()
 345{
 346        # parse $args after "submodule ... add".
 347        reference_path=
 348        while test $# -ne 0
 349        do
 350                case "$1" in
 351                -b | --branch)
 352                        case "$2" in '') usage ;; esac
 353                        branch=$2
 354                        shift
 355                        ;;
 356                -f | --force)
 357                        force=$1
 358                        ;;
 359                -q|--quiet)
 360                        GIT_QUIET=1
 361                        ;;
 362                --reference)
 363                        case "$2" in '') usage ;; esac
 364                        reference_path=$2
 365                        shift
 366                        ;;
 367                --reference=*)
 368                        reference_path="${1#--reference=}"
 369                        ;;
 370                --name)
 371                        case "$2" in '') usage ;; esac
 372                        custom_name=$2
 373                        shift
 374                        ;;
 375                --depth)
 376                        case "$2" in '') usage ;; esac
 377                        depth="--depth=$2"
 378                        shift
 379                        ;;
 380                --depth=*)
 381                        depth=$1
 382                        ;;
 383                --)
 384                        shift
 385                        break
 386                        ;;
 387                -*)
 388                        usage
 389                        ;;
 390                *)
 391                        break
 392                        ;;
 393                esac
 394                shift
 395        done
 396
 397        if test -n "$reference_path"
 398        then
 399                is_absolute_path "$reference_path" ||
 400                reference_path="$wt_prefix$reference_path"
 401
 402                reference="--reference=$reference_path"
 403        fi
 404
 405        repo=$1
 406        sm_path=$2
 407
 408        if test -z "$sm_path"; then
 409                sm_path=$(echo "$repo" |
 410                        sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
 411        fi
 412
 413        if test -z "$repo" -o -z "$sm_path"; then
 414                usage
 415        fi
 416
 417        is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
 418
 419        # assure repo is absolute or relative to parent
 420        case "$repo" in
 421        ./*|../*)
 422                test -z "$wt_prefix" ||
 423                die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
 424
 425                # dereference source url relative to parent's url
 426                realrepo=$(resolve_relative_url "$repo") || exit
 427                ;;
 428        *:*|/*)
 429                # absolute url
 430                realrepo=$repo
 431                ;;
 432        *)
 433                die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
 434        ;;
 435        esac
 436
 437        # normalize path:
 438        # multiple //; leading ./; /./; /../; trailing /
 439        sm_path=$(printf '%s/\n' "$sm_path" |
 440                sed -e '
 441                        s|//*|/|g
 442                        s|^\(\./\)*||
 443                        s|/\./|/|g
 444                        :start
 445                        s|\([^/]*\)/\.\./||
 446                        tstart
 447                        s|/*$||
 448                ')
 449        git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
 450        die "$(eval_gettext "'\$sm_path' already exists in the index")"
 451
 452        if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
 453        then
 454                eval_gettextln "The following path is ignored by one of your .gitignore files:
 455\$sm_path
 456Use -f if you really want to add it." >&2
 457                exit 1
 458        fi
 459
 460        if test -n "$custom_name"
 461        then
 462                sm_name="$custom_name"
 463        else
 464                sm_name="$sm_path"
 465        fi
 466
 467        # perhaps the path exists and is already a git repo, else clone it
 468        if test -e "$sm_path"
 469        then
 470                if test -d "$sm_path"/.git -o -f "$sm_path"/.git
 471                then
 472                        eval_gettextln "Adding existing repo at '\$sm_path' to the index"
 473                else
 474                        die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")"
 475                fi
 476
 477        else
 478                if test -d ".git/modules/$sm_name"
 479                then
 480                        if test -z "$force"
 481                        then
 482                                echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")"
 483                                GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^,"  ", -e s,' (fetch)',, >&2
 484                                echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")"
 485                                echo >&2 "  $realrepo"
 486                                echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")"
 487                                die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")"
 488                        else
 489                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 490                        fi
 491                fi
 492                if test -n "$branch"
 493                then
 494                        start_point="origin/$branch"
 495                        local_branch="$branch"
 496                else
 497                        start_point=""
 498                        local_branch=""
 499                fi
 500                module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" "$start_point" "$local_branch" || exit
 501        fi
 502        git config submodule."$sm_name".url "$realrepo"
 503
 504        git add $force "$sm_path" ||
 505        die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
 506
 507        git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
 508        git config -f .gitmodules submodule."$sm_name".url "$repo" &&
 509        if test -n "$branch"
 510        then
 511                git config -f .gitmodules submodule."$sm_name".branch "$branch"
 512        fi &&
 513        git add --force .gitmodules ||
 514        die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 515}
 516
 517#
 518# Execute an arbitrary command sequence in each checked out
 519# submodule
 520#
 521# $@ = command to execute
 522#
 523cmd_foreach()
 524{
 525        # parse $args after "submodule ... foreach".
 526        while test $# -ne 0
 527        do
 528                case "$1" in
 529                -q|--quiet)
 530                        GIT_QUIET=1
 531                        ;;
 532                --recursive)
 533                        recursive=1
 534                        ;;
 535                -*)
 536                        usage
 537                        ;;
 538                *)
 539                        break
 540                        ;;
 541                esac
 542                shift
 543        done
 544
 545        toplevel=$(pwd)
 546
 547        # dup stdin so that it can be restored when running the external
 548        # command in the subshell (and a recursive call to this function)
 549        exec 3<&0
 550
 551        module_list |
 552        while read mode sha1 stage sm_path
 553        do
 554                die_if_unmatched "$mode"
 555                if test -e "$sm_path"/.git
 556                then
 557                        displaypath=$(relative_path "$sm_path")
 558                        say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
 559                        name=$(module_name "$sm_path")
 560                        (
 561                                prefix="$prefix$sm_path/"
 562                                clear_local_git_env
 563                                cd "$sm_path" &&
 564                                sm_path=$(relative_path "$sm_path") &&
 565                                # we make $path available to scripts ...
 566                                path=$sm_path &&
 567                                eval "$@" &&
 568                                if test -n "$recursive"
 569                                then
 570                                        cmd_foreach "--recursive" "$@"
 571                                fi
 572                        ) <&3 3<&- ||
 573                        die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
 574                fi
 575        done
 576}
 577
 578#
 579# Register submodules in .git/config
 580#
 581# $@ = requested paths (default to all)
 582#
 583cmd_init()
 584{
 585        # parse $args after "submodule ... init".
 586        while test $# -ne 0
 587        do
 588                case "$1" in
 589                -q|--quiet)
 590                        GIT_QUIET=1
 591                        ;;
 592                --)
 593                        shift
 594                        break
 595                        ;;
 596                -*)
 597                        usage
 598                        ;;
 599                *)
 600                        break
 601                        ;;
 602                esac
 603                shift
 604        done
 605
 606        module_list "$@" |
 607        while read mode sha1 stage sm_path
 608        do
 609                die_if_unmatched "$mode"
 610                name=$(module_name "$sm_path") || exit
 611
 612                displaypath=$(relative_path "$sm_path")
 613
 614                # Copy url setting when it is not set yet
 615                if test -z "$(git config "submodule.$name.url")"
 616                then
 617                        url=$(git config -f .gitmodules submodule."$name".url)
 618                        test -z "$url" &&
 619                        die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
 620
 621                        # Possibly a url relative to parent
 622                        case "$url" in
 623                        ./*|../*)
 624                                url=$(resolve_relative_url "$url") || exit
 625                                ;;
 626                        esac
 627                        git config submodule."$name".url "$url" ||
 628                        die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
 629
 630                        say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
 631                fi
 632
 633                # Copy "update" setting when it is not set yet
 634                if upd="$(git config -f .gitmodules submodule."$name".update)" &&
 635                   test -n "$upd" &&
 636                   test -z "$(git config submodule."$name".update)"
 637                then
 638                        case "$upd" in
 639                        checkout | rebase | merge | none)
 640                                ;; # known modes of updating
 641                        *)
 642                                echo >&2 "warning: unknown update mode '$upd' suggested for submodule '$name'"
 643                                upd=none
 644                                ;;
 645                        esac
 646                        git config submodule."$name".update "$upd" ||
 647                        die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 648                fi
 649        done
 650}
 651
 652#
 653# Unregister submodules from .git/config and remove their work tree
 654#
 655# $@ = requested paths (use '.' to deinit all submodules)
 656#
 657cmd_deinit()
 658{
 659        # parse $args after "submodule ... deinit".
 660        while test $# -ne 0
 661        do
 662                case "$1" in
 663                -f|--force)
 664                        force=$1
 665                        ;;
 666                -q|--quiet)
 667                        GIT_QUIET=1
 668                        ;;
 669                --)
 670                        shift
 671                        break
 672                        ;;
 673                -*)
 674                        usage
 675                        ;;
 676                *)
 677                        break
 678                        ;;
 679                esac
 680                shift
 681        done
 682
 683        if test $# = 0
 684        then
 685                die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
 686        fi
 687
 688        module_list "$@" |
 689        while read mode sha1 stage sm_path
 690        do
 691                die_if_unmatched "$mode"
 692                name=$(module_name "$sm_path") || exit
 693
 694                displaypath=$(relative_path "$sm_path")
 695
 696                # Remove the submodule work tree (unless the user already did it)
 697                if test -d "$sm_path"
 698                then
 699                        # Protect submodules containing a .git directory
 700                        if test -d "$sm_path/.git"
 701                        then
 702                                echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
 703                                die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
 704                        fi
 705
 706                        if test -z "$force"
 707                        then
 708                                git rm -qn "$sm_path" ||
 709                                die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
 710                        fi
 711                        rm -rf "$sm_path" &&
 712                        say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
 713                        say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
 714                fi
 715
 716                mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
 717
 718                # Remove the .git/config entries (unless the user already did it)
 719                if test -n "$(git config --get-regexp submodule."$name\.")"
 720                then
 721                        # Remove the whole section so we have a clean state when
 722                        # the user later decides to init this submodule again
 723                        url=$(git config submodule."$name".url)
 724                        git config --remove-section submodule."$name" 2>/dev/null &&
 725                        say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
 726                fi
 727        done
 728}
 729
 730#
 731# Update each submodule path to correct revision, using clone and checkout as needed
 732#
 733# $@ = requested paths (default to all)
 734#
 735cmd_update()
 736{
 737        # parse $args after "submodule ... update".
 738        orig_flags=
 739        while test $# -ne 0
 740        do
 741                case "$1" in
 742                -q|--quiet)
 743                        GIT_QUIET=1
 744                        ;;
 745                -i|--init)
 746                        init=1
 747                        ;;
 748                --remote)
 749                        remote=1
 750                        ;;
 751                -N|--no-fetch)
 752                        nofetch=1
 753                        ;;
 754                -f|--force)
 755                        force=$1
 756                        ;;
 757                -r|--rebase)
 758                        update="rebase"
 759                        ;;
 760                --reference)
 761                        case "$2" in '') usage ;; esac
 762                        reference="--reference=$2"
 763                        orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
 764                        shift
 765                        ;;
 766                --reference=*)
 767                        reference="$1"
 768                        ;;
 769                -m|--merge)
 770                        update="merge"
 771                        ;;
 772                --recursive)
 773                        recursive=1
 774                        ;;
 775                --checkout)
 776                        update="checkout"
 777                        ;;
 778                --depth)
 779                        case "$2" in '') usage ;; esac
 780                        depth="--depth=$2"
 781                        shift
 782                        ;;
 783                --depth=*)
 784                        depth=$1
 785                        ;;
 786                --)
 787                        shift
 788                        break
 789                        ;;
 790                -*)
 791                        usage
 792                        ;;
 793                *)
 794                        break
 795                        ;;
 796                esac
 797                orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
 798                shift
 799        done
 800
 801        if test -n "$init"
 802        then
 803                cmd_init "--" "$@" || return
 804        fi
 805
 806        cloned_modules=
 807        module_list "$@" | {
 808        err=
 809        while read mode sha1 stage sm_path
 810        do
 811                die_if_unmatched "$mode"
 812                if test "$stage" = U
 813                then
 814                        echo >&2 "Skipping unmerged submodule $prefix$sm_path"
 815                        continue
 816                fi
 817                name=$(module_name "$sm_path") || exit
 818                url=$(git config submodule."$name".url)
 819                config_branch=$(get_submodule_config "$name" branch)
 820                branch="${config_branch:-master}"
 821                local_branch="$branch"
 822                if ! test -z "$update"
 823                then
 824                        update_module=$update
 825                else
 826                        update_module=$(git config submodule."$name".update)
 827                        if test -z "$update_module"
 828                        then
 829                                update_module="checkout"
 830                        fi
 831                fi
 832
 833                displaypath=$(relative_path "$prefix$sm_path")
 834
 835                case "$update_module" in
 836                none)
 837                        echo "Skipping submodule '$displaypath'"
 838                        continue
 839                        ;;
 840                checkout)
 841                        local_branch=""
 842                        ;;
 843                rebase | merge | !*)
 844                        ;;
 845                *)
 846                        die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 847                esac
 848
 849                if test -z "$url"
 850                then
 851                        # Only mention uninitialized submodules when its
 852                        # path have been specified
 853                        test "$#" != "0" &&
 854                        say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 855Maybe you want to use 'update --init'?")"
 856                        continue
 857                fi
 858
 859                if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
 860                then
 861                        start_point="origin/${branch}"
 862                        module_clone "$sm_path" "$name" "$url" "$reference" "$depth" "$start_point" "$local_branch" || exit
 863                        cloned_modules="$cloned_modules;$name"
 864                        subsha1=
 865                else
 866                        subsha1=$(clear_local_git_env; cd "$sm_path" &&
 867                                git rev-parse --verify HEAD) ||
 868                        die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 869                fi
 870
 871                if test -n "$remote"
 872                then
 873                        if test -z "$nofetch"
 874                        then
 875                                # Fetch remote before determining tracking $sha1
 876                                (clear_local_git_env; cd "$sm_path" && git-fetch) ||
 877                                die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
 878                        fi
 879                        remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote)
 880                        sha1=$(clear_local_git_env; cd "$sm_path" &&
 881                                git rev-parse --verify "${remote_name}/${branch}") ||
 882                        die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")"
 883                fi
 884
 885                if test "$subsha1" != "$sha1" -o -n "$force"
 886                then
 887                        subforce=$force
 888                        # If we don't already have a -f flag and the submodule has never been checked out
 889                        if test -z "$subsha1" -a -z "$force"
 890                        then
 891                                subforce="-f"
 892                        fi
 893
 894                        if test -z "$nofetch"
 895                        then
 896                                # Run fetch only if $sha1 isn't present or it
 897                                # is not reachable from a ref.
 898                                (clear_local_git_env; cd "$sm_path" &&
 899                                        ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
 900                                         test -z "$rev") || git-fetch)) ||
 901                                die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
 902                        fi
 903
 904                        # Is this something we just cloned?
 905                        case ";$cloned_modules;" in
 906                        *";$name;"*)
 907                                # then there is no local change to integrate
 908                                update_module='!git reset --hard -q'
 909                        esac
 910
 911                        must_die_on_failure=
 912                        case "$update_module" in
 913                        checkout)
 914                                command="git checkout $subforce -q"
 915                                die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
 916                                say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 917                                ;;
 918                        rebase)
 919                                command="git rebase"
 920                                die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
 921                                say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
 922                                must_die_on_failure=yes
 923                                ;;
 924                        merge)
 925                                command="git merge"
 926                                die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
 927                                say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
 928                                must_die_on_failure=yes
 929                                ;;
 930                        !*)
 931                                command="${update_module#!}"
 932                                die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule  path '\$prefix\$sm_path'")"
 933                                say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
 934                                must_die_on_failure=yes
 935                                ;;
 936                        *)
 937                                die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")"
 938                        esac
 939
 940                        if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
 941                        then
 942                                say "$say_msg"
 943                        elif test -n "$must_die_on_failure"
 944                        then
 945                                die_with_status 2 "$die_msg"
 946                        else
 947                                err="${err};$die_msg"
 948                                continue
 949                        fi
 950                fi
 951
 952                if test -n "$recursive"
 953                then
 954                        (
 955                                prefix="$prefix$sm_path/"
 956                                clear_local_git_env
 957                                cd "$sm_path" &&
 958                                eval cmd_update "$orig_flags"
 959                        )
 960                        res=$?
 961                        if test $res -gt 0
 962                        then
 963                                die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
 964                                if test $res -eq 1
 965                                then
 966                                        err="${err};$die_msg"
 967                                        continue
 968                                else
 969                                        die_with_status $res "$die_msg"
 970                                fi
 971                        fi
 972                fi
 973        done
 974
 975        if test -n "$err"
 976        then
 977                OIFS=$IFS
 978                IFS=';'
 979                for e in $err
 980                do
 981                        if test -n "$e"
 982                        then
 983                                echo >&2 "$e"
 984                        fi
 985                done
 986                IFS=$OIFS
 987                exit 1
 988        fi
 989        }
 990}
 991
 992set_name_rev () {
 993        revname=$( (
 994                clear_local_git_env
 995                cd "$1" && {
 996                        git describe "$2" 2>/dev/null ||
 997                        git describe --tags "$2" 2>/dev/null ||
 998                        git describe --contains "$2" 2>/dev/null ||
 999                        git describe --all --always "$2"
1000                }
1001        ) )
1002        test -z "$revname" || revname=" ($revname)"
1003}
1004#
1005# Show commit summary for submodules in index or working tree
1006#
1007# If '--cached' is given, show summary between index and given commit,
1008# or between working tree and given commit
1009#
1010# $@ = [commit (default 'HEAD'),] requested paths (default all)
1011#
1012cmd_summary() {
1013        summary_limit=-1
1014        for_status=
1015        diff_cmd=diff-index
1016
1017        # parse $args after "submodule ... summary".
1018        while test $# -ne 0
1019        do
1020                case "$1" in
1021                --cached)
1022                        cached="$1"
1023                        ;;
1024                --files)
1025                        files="$1"
1026                        ;;
1027                --for-status)
1028                        for_status="$1"
1029                        ;;
1030                -n|--summary-limit)
1031                        summary_limit="$2"
1032                        isnumber "$summary_limit" || usage
1033                        shift
1034                        ;;
1035                --summary-limit=*)
1036                        summary_limit="${1#--summary-limit=}"
1037                        isnumber "$summary_limit" || usage
1038                        ;;
1039                --)
1040                        shift
1041                        break
1042                        ;;
1043                -*)
1044                        usage
1045                        ;;
1046                *)
1047                        break
1048                        ;;
1049                esac
1050                shift
1051        done
1052
1053        test $summary_limit = 0 && return
1054
1055        if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
1056        then
1057                head=$rev
1058                test $# = 0 || shift
1059        elif test -z "$1" -o "$1" = "HEAD"
1060        then
1061                # before the first commit: compare with an empty tree
1062                head=$(git hash-object -w -t tree --stdin </dev/null)
1063                test -z "$1" || shift
1064        else
1065                head="HEAD"
1066        fi
1067
1068        if [ -n "$files" ]
1069        then
1070                test -n "$cached" &&
1071                die "$(gettext "The --cached option cannot be used with the --files option")"
1072                diff_cmd=diff-files
1073                head=
1074        fi
1075
1076        cd_to_toplevel
1077        eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
1078        # Get modified modules cared by user
1079        modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
1080                sane_egrep '^:([0-7]* )?160000' |
1081                while read mod_src mod_dst sha1_src sha1_dst status sm_path
1082                do
1083                        # Always show modules deleted or type-changed (blob<->module)
1084                        test $status = D -o $status = T && echo "$sm_path" && continue
1085                        # Respect the ignore setting for --for-status.
1086                        if test -n "$for_status"
1087                        then
1088                                name=$(module_name "$sm_path")
1089                                ignore_config=$(get_submodule_config "$name" ignore none)
1090                                test $status != A -a $ignore_config = all && continue
1091                        fi
1092                        # Also show added or modified modules which are checked out
1093                        GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
1094                        echo "$sm_path"
1095                done
1096        )
1097
1098        test -z "$modules" && return
1099
1100        git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
1101        sane_egrep '^:([0-7]* )?160000' |
1102        cut -c2- |
1103        while read mod_src mod_dst sha1_src sha1_dst status name
1104        do
1105                if test -z "$cached" &&
1106                        test $sha1_dst = 0000000000000000000000000000000000000000
1107                then
1108                        case "$mod_dst" in
1109                        160000)
1110                                sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
1111                                ;;
1112                        100644 | 100755 | 120000)
1113                                sha1_dst=$(git hash-object $name)
1114                                ;;
1115                        000000)
1116                                ;; # removed
1117                        *)
1118                                # unexpected type
1119                                eval_gettextln "unexpected mode \$mod_dst" >&2
1120                                continue ;;
1121                        esac
1122                fi
1123                missing_src=
1124                missing_dst=
1125
1126                test $mod_src = 160000 &&
1127                ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
1128                missing_src=t
1129
1130                test $mod_dst = 160000 &&
1131                ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
1132                missing_dst=t
1133
1134                display_name=$(relative_path "$name")
1135
1136                total_commits=
1137                case "$missing_src,$missing_dst" in
1138                t,)
1139                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_src")"
1140                        ;;
1141                ,t)
1142                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_dst")"
1143                        ;;
1144                t,t)
1145                        errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
1146                        ;;
1147                *)
1148                        errmsg=
1149                        total_commits=$(
1150                        if test $mod_src = 160000 -a $mod_dst = 160000
1151                        then
1152                                range="$sha1_src...$sha1_dst"
1153                        elif test $mod_src = 160000
1154                        then
1155                                range=$sha1_src
1156                        else
1157                                range=$sha1_dst
1158                        fi
1159                        GIT_DIR="$name/.git" \
1160                        git rev-list --first-parent $range -- | wc -l
1161                        )
1162                        total_commits=" ($(($total_commits + 0)))"
1163                        ;;
1164                esac
1165
1166                sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
1167                sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
1168                if test $status = T
1169                then
1170                        blob="$(gettext "blob")"
1171                        submodule="$(gettext "submodule")"
1172                        if test $mod_dst = 160000
1173                        then
1174                                echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
1175                        else
1176                                echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
1177                        fi
1178                else
1179                        echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
1180                fi
1181                if test -n "$errmsg"
1182                then
1183                        # Don't give error msg for modification whose dst is not submodule
1184                        # i.e. deleted or changed to blob
1185                        test $mod_dst = 160000 && echo "$errmsg"
1186                else
1187                        if test $mod_src = 160000 -a $mod_dst = 160000
1188                        then
1189                                limit=
1190                                test $summary_limit -gt 0 && limit="-$summary_limit"
1191                                GIT_DIR="$name/.git" \
1192                                git log $limit --pretty='format:  %m %s' \
1193                                --first-parent $sha1_src...$sha1_dst
1194                        elif test $mod_dst = 160000
1195                        then
1196                                GIT_DIR="$name/.git" \
1197                                git log --pretty='format:  > %s' -1 $sha1_dst
1198                        else
1199                                GIT_DIR="$name/.git" \
1200                                git log --pretty='format:  < %s' -1 $sha1_src
1201                        fi
1202                        echo
1203                fi
1204                echo
1205        done
1206}
1207#
1208# List all submodules, prefixed with:
1209#  - submodule not initialized
1210#  + different revision checked out
1211#
1212# If --cached was specified the revision in the index will be printed
1213# instead of the currently checked out revision.
1214#
1215# $@ = requested paths (default to all)
1216#
1217cmd_status()
1218{
1219        # parse $args after "submodule ... status".
1220        while test $# -ne 0
1221        do
1222                case "$1" in
1223                -q|--quiet)
1224                        GIT_QUIET=1
1225                        ;;
1226                --cached)
1227                        cached=1
1228                        ;;
1229                --recursive)
1230                        recursive=1
1231                        ;;
1232                --)
1233                        shift
1234                        break
1235                        ;;
1236                -*)
1237                        usage
1238                        ;;
1239                *)
1240                        break
1241                        ;;
1242                esac
1243                shift
1244        done
1245
1246        module_list "$@" |
1247        while read mode sha1 stage sm_path
1248        do
1249                die_if_unmatched "$mode"
1250                name=$(module_name "$sm_path") || exit
1251                url=$(git config submodule."$name".url)
1252                displaypath=$(relative_path "$prefix$sm_path")
1253                if test "$stage" = U
1254                then
1255                        say "U$sha1 $displaypath"
1256                        continue
1257                fi
1258                if test -z "$url" || ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
1259                then
1260                        say "-$sha1 $displaypath"
1261                        continue;
1262                fi
1263                if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
1264                then
1265                        set_name_rev "$sm_path" "$sha1"
1266                        say " $sha1 $displaypath$revname"
1267                else
1268                        if test -z "$cached"
1269                        then
1270                                sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
1271                        fi
1272                        set_name_rev "$sm_path" "$sha1"
1273                        say "+$sha1 $displaypath$revname"
1274                fi
1275
1276                if test -n "$recursive"
1277                then
1278                        (
1279                                prefix="$displaypath/"
1280                                clear_local_git_env
1281                                cd "$sm_path" &&
1282                                eval cmd_status
1283                        ) ||
1284                        die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
1285                fi
1286        done
1287}
1288#
1289# Sync remote urls for submodules
1290# This makes the value for remote.$remote.url match the value
1291# specified in .gitmodules.
1292#
1293cmd_sync()
1294{
1295        while test $# -ne 0
1296        do
1297                case "$1" in
1298                -q|--quiet)
1299                        GIT_QUIET=1
1300                        shift
1301                        ;;
1302                --recursive)
1303                        recursive=1
1304                        shift
1305                        ;;
1306                --)
1307                        shift
1308                        break
1309                        ;;
1310                -*)
1311                        usage
1312                        ;;
1313                *)
1314                        break
1315                        ;;
1316                esac
1317        done
1318        cd_to_toplevel
1319        module_list "$@" |
1320        while read mode sha1 stage sm_path
1321        do
1322                die_if_unmatched "$mode"
1323                name=$(module_name "$sm_path")
1324                url=$(git config -f .gitmodules --get submodule."$name".url)
1325
1326                # Possibly a url relative to parent
1327                case "$url" in
1328                ./*|../*)
1329                        # rewrite foo/bar as ../.. to find path from
1330                        # submodule work tree to superproject work tree
1331                        up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" &&
1332                        # guarantee a trailing /
1333                        up_path=${up_path%/}/ &&
1334                        # path from submodule work tree to submodule origin repo
1335                        sub_origin_url=$(resolve_relative_url "$url" "$up_path") &&
1336                        # path from superproject work tree to submodule origin repo
1337                        super_config_url=$(resolve_relative_url "$url") || exit
1338                        ;;
1339                *)
1340                        sub_origin_url="$url"
1341                        super_config_url="$url"
1342                        ;;
1343                esac
1344
1345                if git config "submodule.$name.url" >/dev/null 2>/dev/null
1346                then
1347                        displaypath=$(relative_path "$prefix$sm_path")
1348                        say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
1349                        git config submodule."$name".url "$super_config_url"
1350
1351                        if test -e "$sm_path"/.git
1352                        then
1353                        (
1354                                clear_local_git_env
1355                                cd "$sm_path"
1356                                remote=$(get_default_remote)
1357                                git config remote."$remote".url "$sub_origin_url"
1358
1359                                if test -n "$recursive"
1360                                then
1361                                        prefix="$prefix$sm_path/"
1362                                        eval cmd_sync
1363                                fi
1364                        )
1365                        fi
1366                fi
1367        done
1368}
1369
1370# This loop parses the command line arguments to find the
1371# subcommand name to dispatch.  Parsing of the subcommand specific
1372# options are primarily done by the subcommand implementations.
1373# Subcommand specific options such as --branch and --cached are
1374# parsed here as well, for backward compatibility.
1375
1376while test $# != 0 && test -z "$command"
1377do
1378        case "$1" in
1379        add | foreach | init | deinit | update | status | summary | sync)
1380                command=$1
1381                ;;
1382        -q|--quiet)
1383                GIT_QUIET=1
1384                ;;
1385        -b|--branch)
1386                case "$2" in
1387                '')
1388                        usage
1389                        ;;
1390                esac
1391                branch="$2"; shift
1392                ;;
1393        --cached)
1394                cached="$1"
1395                ;;
1396        --)
1397                break
1398                ;;
1399        -*)
1400                usage
1401                ;;
1402        *)
1403                break
1404                ;;
1405        esac
1406        shift
1407done
1408
1409# No command word defaults to "status"
1410if test -z "$command"
1411then
1412    if test $# = 0
1413    then
1414        command=status
1415    else
1416        usage
1417    fi
1418fi
1419
1420# "-b branch" is accepted only by "add"
1421if test -n "$branch" && test "$command" != add
1422then
1423        usage
1424fi
1425
1426# "--cached" is accepted only by "status" and "summary"
1427if test -n "$cached" && test "$command" != status -a "$command" != summary
1428then
1429        usage
1430fi
1431
1432"cmd_$command" "$@"