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