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