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