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