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