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