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 25# Restrict ourselves to a vanilla subset of protocols; the URLs 26# we get are under control of a remote repository, and we do not 27# want them kicking off arbitrary git-remote-* programs. 28# 29# If the user has already specified a set of allowed protocols, 30# we assume they know what they're doing and use that instead. 31:${GIT_ALLOW_PROTOCOL=file:git:http:https:ssh} 32export GIT_ALLOW_PROTOCOL 33 34command= 35branch= 36force= 37reference= 38cached= 39recursive= 40init= 41files= 42remote= 43nofetch= 44update= 45prefix= 46custom_name= 47depth= 48 49# The function takes at most 2 arguments. The first argument is the 50# URL that navigates to the submodule origin repo. When relative, this URL 51# is relative to the superproject origin URL repo. The second up_path 52# argument, if specified, is the relative path that navigates 53# from the submodule working tree to the superproject working tree. 54# 55# The output of the function is the origin URL of the submodule. 56# 57# The output will either be an absolute URL or filesystem path (if the 58# superproject origin URL is an absolute URL or filesystem path, 59# respectively) or a relative file system path (if the superproject 60# origin URL is a relative file system path). 61# 62# When the output is a relative file system path, the path is either 63# relative to the submodule working tree, if up_path is specified, or to 64# the superproject working tree otherwise. 65resolve_relative_url () 66{ 67 remote=$(get_default_remote) 68 remoteurl=$(git config "remote.$remote.url")|| 69 remoteurl=$(pwd)# the repository is its own authoritative upstream 70 url="$1" 71 remoteurl=${remoteurl%/} 72 sep=/ 73 up_path="$2" 74 75case"$remoteurl"in 76*:*|/*) 77 is_relative= 78;; 79 ./*|../*) 80 is_relative=t 81;; 82*) 83 is_relative=t 84 remoteurl="./$remoteurl" 85;; 86esac 87 88whiletest -n"$url" 89do 90case"$url"in 91 ../*) 92 url="${url#../}" 93case"$remoteurl"in 94*/*) 95 remoteurl="${remoteurl%/*}" 96;; 97*:*) 98 remoteurl="${remoteurl%:*}" 99 sep=: 100;; 101*) 102iftest -z"$is_relative"||test"."="$remoteurl" 103then 104 die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")" 105else 106 remoteurl=. 107fi 108;; 109esac 110;; 111 ./*) 112 url="${url#./}" 113;; 114*) 115break;; 116esac 117done 118 remoteurl="$remoteurl$sep${url%/}" 119echo"${is_relative:+${up_path}}${remoteurl#./}" 120} 121 122# Resolve a path to be relative to another path. This is intended for 123# converting submodule paths when git-submodule is run in a subdirectory 124# and only handles paths where the directory separator is '/'. 125# 126# The output is the first argument as a path relative to the second argument, 127# which defaults to $wt_prefix if it is omitted. 128relative_path () 129{ 130local target curdir result 131 target=$1 132 curdir=${2-$wt_prefix} 133 curdir=${curdir%/} 134 result= 135 136whiletest -n"$curdir" 137do 138case"$target"in 139"$curdir/"*) 140 target=${target#"$curdir"/} 141break 142;; 143esac 144 145 result="${result}../" 146iftest"$curdir"="${curdir%/*}" 147then 148 curdir= 149else 150 curdir="${curdir%/*}" 151fi 152done 153 154echo"$result$target" 155} 156 157# 158# Get submodule info for registered submodules 159# $@ = path to limit submodule list 160# 161module_list() 162{ 163eval"set$(git rev-parse --sq --prefix "$wt_prefix" -- "$@")" 164( 165 git ls-files -z --error-unmatch --stage --"$@"|| 166echo"unmatched pathspec exists" 167) | 168 @@PERL@@ -e' 169 my %unmerged = (); 170 my ($null_sha1) = ("0" x 40); 171 my @out = (); 172 my$unmatched= 0; 173 $/ = "\0"; 174 while (<STDIN>) { 175 if (/^unmatched pathspec/) { 176$unmatched= 1; 177 next; 178 } 179 chomp; 180 my ($mode,$sha1,$stage,$path) = 181 /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/; 182 next unless$modeeq "160000"; 183 if ($stagene "0") { 184 if (!$unmerged{$path}++) { 185 push @out, "$mode$null_sha1U\t$path\n"; 186 } 187 next; 188 } 189 push @out, "$_\n"; 190 } 191 if ($unmatched) { 192 print "#unmatched\n"; 193 } else { 194 print for (@out); 195 } 196 ' 197} 198 199die_if_unmatched () 200{ 201iftest"$1"="#unmatched" 202then 203exit1 204fi 205} 206 207# 208# Print a submodule configuration setting 209# 210# $1 = submodule name 211# $2 = option name 212# $3 = default value 213# 214# Checks in the usual git-config places first (for overrides), 215# otherwise it falls back on .gitmodules. This allows you to 216# distribute project-wide defaults in .gitmodules, while still 217# customizing individual repositories if necessary. If the option is 218# not in .gitmodules either, print a default value. 219# 220get_submodule_config () { 221 name="$1" 222 option="$2" 223 default="$3" 224 value=$(git config submodule."$name"."$option") 225iftest -z"$value" 226then 227 value=$(git config -f .gitmodules submodule."$name"."$option") 228fi 229printf'%s'"${value:-$default}" 230} 231 232 233# 234# Map submodule path to submodule name 235# 236# $1 = path 237# 238module_name() 239{ 240# Do we have "submodule.<something>.path = $1" defined in .gitmodules file? 241 sm_path="$1" 242 re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g') 243 name=$( git config -f .gitmodules --get-regexp'^submodule\..*\.path$'| 244sed-n -e's|^submodule\.\(.*\)\.path '"$re"'$|\1|p') 245test -z"$name"&& 246 die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")" 247printf'%s\n'"$name" 248} 249 250# 251# Clone a submodule 252# 253# $1 = submodule path 254# $2 = submodule name 255# $3 = URL to clone 256# $4 = reference repository to reuse (empty for independent) 257# $5 = depth argument for shallow clones (empty for deep) 258# 259# Prior to calling, cmd_update checks that a possibly existing 260# path is not a git repository. 261# Likewise, cmd_add checks that path does not exist at all, 262# since it is the location of a new submodule. 263# 264module_clone() 265{ 266 sm_path=$1 267 name=$2 268 url=$3 269 reference="$4" 270 depth="$5" 271 quiet= 272iftest -n"$GIT_QUIET" 273then 274 quiet=-q 275fi 276 277 gitdir= 278 gitdir_base= 279 base_name=$(dirname "$name") 280 281 gitdir=$(git rev-parse --git-dir) 282 gitdir_base="$gitdir/modules/$base_name" 283 gitdir="$gitdir/modules/$name" 284 285iftest -d"$gitdir" 286then 287mkdir-p"$sm_path" 288rm-f"$gitdir/index" 289else 290mkdir-p"$gitdir_base" 291( 292 clear_local_git_env 293 git clone $quiet ${depth:+"$depth"}-n${reference:+"$reference"} \ 294--separate-git-dir"$gitdir""$url""$sm_path" 295) || 296 die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")" 297fi 298 299# We already are at the root of the work tree but cd_to_toplevel will 300# resolve any symlinks that might be present in $PWD 301 a=$(cd_to_toplevel && cd "$gitdir" && pwd)/ 302 b=$(cd_to_toplevel && cd "$sm_path" && pwd)/ 303# Remove all common leading directories after a sanity check 304iftest"${a#$b}"!="$a"||test"${b#$a}"!="$b";then 305 die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")" 306fi 307whiletest"${a%%/*}"="${b%%/*}" 308do 309 a=${a#*/} 310 b=${b#*/} 311done 312# Now chop off the trailing '/'s that were added in the beginning 313 a=${a%/} 314 b=${b%/} 315 316# Turn each leading "*/" component into "../" 317 rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g') 318printf'%s\n'"gitdir:$rel/$a">"$sm_path/.git" 319 320 rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g') 321(clear_local_git_env;cd"$sm_path"&& GIT_WORK_TREE=. git config core.worktree "$rel/$b") 322} 323 324isnumber() 325{ 326 n=$(($1 + 0))2>/dev/null &&test"$n"="$1" 327} 328 329# 330# Add a new submodule to the working tree, .gitmodules and the index 331# 332# $@ = repo path 333# 334# optional branch is stored in global branch variable 335# 336cmd_add() 337{ 338# parse $args after "submodule ... add". 339 reference_path= 340whiletest$#-ne0 341do 342case"$1"in 343-b|--branch) 344case"$2"in'') usage ;;esac 345 branch=$2 346shift 347;; 348-f|--force) 349 force=$1 350;; 351-q|--quiet) 352 GIT_QUIET=1 353;; 354--reference) 355case"$2"in'') usage ;;esac 356 reference_path=$2 357shift 358;; 359--reference=*) 360 reference_path="${1#--reference=}" 361;; 362--name) 363case"$2"in'') usage ;;esac 364 custom_name=$2 365shift 366;; 367--depth) 368case"$2"in'') usage ;;esac 369 depth="--depth=$2" 370shift 371;; 372--depth=*) 373 depth=$1 374;; 375--) 376shift 377break 378;; 379-*) 380 usage 381;; 382*) 383break 384;; 385esac 386shift 387done 388 389iftest -n"$reference_path" 390then 391 is_absolute_path "$reference_path"|| 392 reference_path="$wt_prefix$reference_path" 393 394 reference="--reference=$reference_path" 395fi 396 397 repo=$1 398 sm_path=$2 399 400iftest -z"$sm_path";then 401 sm_path=$(printf'%s\n'"$repo"| 402sed-e's|/$||'-e's|:*/*\.git$||'-e's|.*[/:]||g') 403fi 404 405iftest -z"$repo"||test -z"$sm_path";then 406 usage 407fi 408 409 is_absolute_path "$sm_path"|| sm_path="$wt_prefix$sm_path" 410 411# assure repo is absolute or relative to parent 412case"$repo"in 413 ./*|../*) 414test -z"$wt_prefix"|| 415 die "$(gettext "Relative path can only be used from the toplevel of the working tree")" 416 417# dereference source url relative to parent's url 418 realrepo=$(resolve_relative_url "$repo")||exit 419;; 420*:*|/*) 421# absolute url 422 realrepo=$repo 423;; 424*) 425 die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")" 426;; 427esac 428 429# normalize path: 430# multiple //; leading ./; /./; /../; trailing / 431 sm_path=$(printf'%s/\n'"$sm_path"| 432sed-e' 433 s|//*|/|g 434 s|^\(\./\)*|| 435 s|/\(\./\)*|/|g 436 :start 437 s|\([^/]*\)/\.\./|| 438 tstart 439 s|/*$|| 440 ') 441 git ls-files --error-unmatch"$sm_path"> /dev/null 2>&1&& 442 die "$(eval_gettext "'\$sm_path' already exists in the index")" 443 444iftest -z"$force"&& ! git add --dry-run --ignore-missing"$sm_path"> /dev/null 2>&1 445then 446 eval_gettextln "The following path is ignored by one of your .gitignore files: 447\$sm_path 448Use -f if you really want to add it.">&2 449exit1 450fi 451 452iftest -n"$custom_name" 453then 454 sm_name="$custom_name" 455else 456 sm_name="$sm_path" 457fi 458 459# perhaps the path exists and is already a git repo, else clone it 460iftest -e"$sm_path" 461then 462iftest -d"$sm_path"/.git ||test -f"$sm_path"/.git 463then 464 eval_gettextln "Adding existing repo at '\$sm_path' to the index" 465else 466 die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")" 467fi 468 469else 470iftest -d".git/modules/$sm_name" 471then 472iftest -z"$force" 473then 474echo>&2"$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")" 475 GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^,"", -e s,' (fetch)',, >&2 476 echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")" 477 echo >&2 "$realrepo" 478 echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")" 479 die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")" 480 else 481 echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")" 482 fi 483 fi 484 module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit 485 ( 486 clear_local_git_env 487 cd "$sm_path" && 488 # ash fails to wordsplit${branch:+-b "$branch"...} 489 case "$branch" in 490 '') git checkout -f -q ;; 491 ?*) git checkout -f -q -B "$branch" "origin/$branch" ;; 492 esac 493 ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")" 494 fi 495 git config submodule."$sm_name".url "$realrepo" 496 497 git add$force"$sm_path" || 498 die "$(eval_gettext "Failed to add submodule '\$sm_path'")" 499 500 git config -f .gitmodules submodule."$sm_name".path "$sm_path" && 501 git config -f .gitmodules submodule."$sm_name".url "$repo" && 502 if test -n "$branch" 503 then 504 git config -f .gitmodules submodule."$sm_name".branch "$branch" 505 fi && 506 git add --force .gitmodules || 507 die "$(eval_gettext "Failed to register submodule '\$sm_path'")" 508} 509 510# 511# Execute an arbitrary command sequence in each checked out 512# submodule 513# 514# $@ = command to execute 515# 516cmd_foreach() 517{ 518 # parse$argsafter "submodule ... foreach". 519 while test$#-ne 0 520 do 521 case "$1" in 522 -q|--quiet) 523 GIT_QUIET=1 524 ;; 525 --recursive) 526 recursive=1 527 ;; 528 -*) 529 usage 530 ;; 531 *) 532 break 533 ;; 534 esac 535 shift 536 done 537 538 toplevel=$(pwd) 539 540 # dup stdin so that it can be restored when running the external 541 # command in the subshell (and a recursive call to this function) 542 exec 3<&0 543 544 module_list | 545 while read mode sha1 stage sm_path 546 do 547 die_if_unmatched "$mode" 548 if test -e "$sm_path"/.git 549 then 550 displaypath=$(relative_path "$sm_path") 551 say "$(eval_gettext "Entering '\$prefix\$displaypath'")" 552 name=$(module_name "$sm_path") 553 ( 554 prefix="$prefix$sm_path/" 555 clear_local_git_env 556 cd "$sm_path" && 557 sm_path=$(relative_path "$sm_path")&& 558 # we make$pathavailable to scripts ... 559 path=$sm_path&& 560 if test$#-eq 1 561 then 562 eval "$1" 563 else 564 "$@" 565 fi && 566 if test -n "$recursive" 567 then 568 cmd_foreach "--recursive" "$@" 569 fi 570 ) <&3 3<&- || 571 die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")" 572 fi 573 done 574} 575 576# 577# Register submodules in .git/config 578# 579# $@ = requested paths (default to all) 580# 581cmd_init() 582{ 583 # parse$argsafter "submodule ... init". 584 while test$#-ne 0 585 do 586 case "$1" in 587 -q|--quiet) 588 GIT_QUIET=1 589 ;; 590 --) 591 shift 592 break 593 ;; 594 -*) 595 usage 596 ;; 597 *) 598 break 599 ;; 600 esac 601 shift 602 done 603 604 module_list "$@" | 605 while read mode sha1 stage sm_path 606 do 607 die_if_unmatched "$mode" 608 name=$(module_name "$sm_path")|| exit 609 610 displaypath=$(relative_path "$sm_path") 611 612 # Copy url setting when it is not set yet 613 if test -z "$(git config "submodule.$name.url")" 614 then 615 url=$(git config -f .gitmodules submodule."$name".url) 616 test -z "$url" && 617 die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")" 618 619 # Possibly a url relative to parent 620 case "$url" in 621 ./*|../*) 622 url=$(resolve_relative_url "$url")|| exit 623 ;; 624 esac 625 git config submodule."$name".url "$url" || 626 die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")" 627 628 say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")" 629fi 630 631# Copy "update" setting when it is not set yet 632if upd="$(git config -f .gitmodules submodule."$name".update)"&& 633test -n"$upd"&& 634test -z"$(git config submodule."$name".update)" 635then 636case"$upd"in 637 checkout | rebase | merge | none) 638;;# known modes of updating 639*) 640echo>&2"warning: unknown update mode '$upd' suggested for submodule '$name'" 641 upd=none 642;; 643esac 644 git config submodule."$name".update "$upd"|| 645 die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")" 646fi 647done 648} 649 650# 651# Unregister submodules from .git/config and remove their work tree 652# 653# $@ = requested paths (use '.' to deinit all submodules) 654# 655cmd_deinit() 656{ 657# parse $args after "submodule ... deinit". 658whiletest$#-ne0 659do 660case"$1"in 661-f|--force) 662 force=$1 663;; 664-q|--quiet) 665 GIT_QUIET=1 666;; 667--) 668shift 669break 670;; 671-*) 672 usage 673;; 674*) 675break 676;; 677esac 678shift 679done 680 681iftest$#=0 682then 683 die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")" 684fi 685 686 module_list "$@"| 687whileread mode sha1 stage sm_path 688do 689 die_if_unmatched "$mode" 690 name=$(module_name "$sm_path")||exit 691 692 displaypath=$(relative_path "$sm_path") 693 694# Remove the submodule work tree (unless the user already did it) 695iftest -d"$sm_path" 696then 697# Protect submodules containing a .git directory 698iftest -d"$sm_path/.git" 699then 700echo>&2"$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")" 701 die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")" 702 fi 703 704 if test -z "$force" 705 then 706 git rm -qn "$sm_path" || 707 die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")" 708 fi 709 rm -rf "$sm_path" && 710 say "$(eval_gettext "Cleared directory '\$displaypath'")" || 711 say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")" 712 fi 713 714 mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")" 715 716 # Remove the .git/config entries (unless the user already did it) 717 if test -n "$(git config --get-regexp submodule."$name\.")" 718 then 719 # Remove the whole section so we have a clean state when 720 # the user later decides to init this submodule again 721 url=$(git config submodule."$name".url) 722 git config --remove-section submodule."$name" 2>/dev/null && 723 say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")" 724fi 725done 726} 727 728# 729# Update each submodule path to correct revision, using clone and checkout as needed 730# 731# $@ = requested paths (default to all) 732# 733cmd_update() 734{ 735# parse $args after "submodule ... update". 736whiletest$#-ne0 737do 738case"$1"in 739-q|--quiet) 740 GIT_QUIET=1 741;; 742-i|--init) 743 init=1 744;; 745--remote) 746 remote=1 747;; 748-N|--no-fetch) 749 nofetch=1 750;; 751-f|--force) 752 force=$1 753;; 754-r|--rebase) 755 update="rebase" 756;; 757--reference) 758case"$2"in'') usage ;;esac 759 reference="--reference=$2" 760shift 761;; 762--reference=*) 763 reference="$1" 764;; 765-m|--merge) 766 update="merge" 767;; 768--recursive) 769 recursive=1 770;; 771--checkout) 772 update="checkout" 773;; 774--depth) 775case"$2"in'') usage ;;esac 776 depth="--depth=$2" 777shift 778;; 779--depth=*) 780 depth=$1 781;; 782--) 783shift 784break 785;; 786-*) 787 usage 788;; 789*) 790break 791;; 792esac 793shift 794done 795 796iftest -n"$init" 797then 798 cmd_init "--""$@"||return 799fi 800 801 cloned_modules= 802 module_list "$@"| { 803 err= 804whileread mode sha1 stage sm_path 805do 806 die_if_unmatched "$mode" 807iftest"$stage"= U 808then 809echo>&2"Skipping unmerged submodule$prefix$sm_path" 810continue 811fi 812 name=$(module_name "$sm_path")||exit 813 url=$(git config submodule."$name".url) 814 branch=$(get_submodule_config "$name" branch master) 815if!test -z"$update" 816then 817 update_module=$update 818else 819 update_module=$(git config submodule."$name".update) 820iftest -z"$update_module" 821then 822 update_module="checkout" 823fi 824fi 825 826 displaypath=$(relative_path "$prefix$sm_path") 827 828iftest"$update_module"="none" 829then 830echo"Skipping submodule '$displaypath'" 831continue 832fi 833 834iftest -z"$url" 835then 836# Only mention uninitialized submodules when its 837# path have been specified 838test"$#"!="0"&& 839 say "$(eval_gettext "Submodule path '\$displaypath' not initialized 840Maybe you want to use 'update --init'?")" 841continue 842fi 843 844if!test -d"$sm_path"/.git && !test -f"$sm_path"/.git 845then 846 module_clone "$sm_path""$name""$url""$reference""$depth"||exit 847 cloned_modules="$cloned_modules;$name" 848 subsha1= 849else 850 subsha1=$(clear_local_git_env;cd"$sm_path"&& 851 git rev-parse --verify HEAD) || 852 die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")" 853fi 854 855iftest -n"$remote" 856then 857iftest -z"$nofetch" 858then 859# Fetch remote before determining tracking $sha1 860(clear_local_git_env;cd"$sm_path"&& git-fetch) || 861 die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")" 862fi 863 remote_name=$(clear_local_git_env; cd "$sm_path" && get_default_remote) 864 sha1=$(clear_local_git_env;cd"$sm_path"&& 865 git rev-parse --verify"${remote_name}/${branch}") || 866 die "$(eval_gettext "Unable to find current ${remote_name}/${branch} revision in submodule path '\$sm_path'")" 867fi 868 869iftest"$subsha1"!="$sha1"||test -n"$force" 870then 871 subforce=$force 872# If we don't already have a -f flag and the submodule has never been checked out 873iftest -z"$subsha1"&&test -z"$force" 874then 875 subforce="-f" 876fi 877 878iftest -z"$nofetch" 879then 880# Run fetch only if $sha1 isn't present or it 881# is not reachable from a ref. 882(clear_local_git_env;cd"$sm_path"&& 883( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null)&& 884test -z"$rev") || git-fetch)) || 885 die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")" 886fi 887 888# Is this something we just cloned? 889case";$cloned_modules;"in 890*";$name;"*) 891# then there is no local change to integrate 892 update_module=checkout ;; 893esac 894 895 must_die_on_failure= 896case"$update_module"in 897 checkout) 898command="git checkout$subforce-q" 899 die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")" 900 say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")" 901;; 902 rebase) 903command="git rebase" 904 die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")" 905 say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")" 906 must_die_on_failure=yes 907;; 908 merge) 909command="git merge" 910 die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")" 911 say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")" 912 must_die_on_failure=yes 913;; 914!*) 915command="${update_module#!}" 916 die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")" 917 say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")" 918 must_die_on_failure=yes 919;; 920*) 921 die "$(eval_gettext "Invalid update mode '$update_module' for submodule '$name'")" 922esac 923 924if(clear_local_git_env;cd"$sm_path"&&$command"$sha1") 925then 926 say "$say_msg" 927eliftest -n"$must_die_on_failure" 928then 929 die_with_status 2"$die_msg" 930else 931 err="${err};$die_msg" 932continue 933fi 934fi 935 936iftest -n"$recursive" 937then 938( 939 prefix="$prefix$sm_path/" 940 clear_local_git_env 941cd"$sm_path"&& 942eval cmd_update 943) 944 res=$? 945iftest$res-gt0 946then 947 die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")" 948iftest$res-eq1 949then 950 err="${err};$die_msg" 951continue 952else 953 die_with_status $res"$die_msg" 954fi 955fi 956fi 957done 958 959iftest -n"$err" 960then 961 OIFS=$IFS 962 IFS=';' 963for e in$err 964do 965iftest -n"$e" 966then 967echo>&2"$e" 968fi 969done 970 IFS=$OIFS 971exit1 972fi 973} 974} 975 976set_name_rev () { 977 revname=$( ( 978 clear_local_git_env 979cd"$1"&& { 980 git describe "$2"2>/dev/null || 981 git describe --tags"$2"2>/dev/null || 982 git describe --contains"$2"2>/dev/null || 983 git describe --all --always"$2" 984} 985) ) 986test -z"$revname"|| revname=" ($revname)" 987} 988# 989# Show commit summary for submodules in index or working tree 990# 991# If '--cached' is given, show summary between index and given commit, 992# or between working tree and given commit 993# 994# $@ = [commit (default 'HEAD'),] requested paths (default all) 995# 996cmd_summary() { 997 summary_limit=-1 998 for_status= 999 diff_cmd=diff-index10001001# parse $args after "submodule ... summary".1002whiletest$#-ne01003do1004case"$1"in1005--cached)1006 cached="$1"1007;;1008--files)1009 files="$1"1010;;1011--for-status)1012 for_status="$1"1013;;1014-n|--summary-limit)1015 summary_limit="$2"1016 isnumber "$summary_limit"|| usage1017shift1018;;1019--summary-limit=*)1020 summary_limit="${1#--summary-limit=}"1021 isnumber "$summary_limit"|| usage1022;;1023--)1024shift1025break1026;;1027-*)1028 usage1029;;1030*)1031break1032;;1033esac1034shift1035done10361037test$summary_limit=0&&return10381039ifrev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})1040then1041head=$rev1042test$#=0||shift1043eliftest -z"$1"||test"$1"="HEAD"1044then1045# before the first commit: compare with an empty tree1046head=$(git hash-object -w -t tree --stdin </dev/null)1047test -z"$1"||shift1048else1049head="HEAD"1050fi10511052if[-n"$files"]1053then1054test -n"$cached"&&1055 die "$(gettext "The --cached option cannot be used with the --files option")"1056 diff_cmd=diff-files1057head=1058fi10591060 cd_to_toplevel1061eval"set$(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"1062# Get modified modules cared by user1063 modules=$(git $diff_cmd $cached--ignore-submodules=dirty --raw$head--"$@"|1064 sane_egrep '^:([0-7]* )?160000'|1065whileread mod_src mod_dst sha1_src sha1_dst status sm_path1066do1067# Always show modules deleted or type-changed (blob<->module)1068iftest"$status"= D ||test"$status"= T1069then1070printf'%s\n'"$sm_path"1071continue1072fi1073# Respect the ignore setting for --for-status.1074iftest -n"$for_status"1075then1076 name=$(module_name "$sm_path")1077 ignore_config=$(get_submodule_config "$name" ignore none)1078test$status!= A &&test$ignore_config= all &&continue1079fi1080# Also show added or modified modules which are checked out1081 GIT_DIR="$sm_path/.git" git-rev-parse --git-dir>/dev/null 2>&1&&1082printf'%s\n'"$sm_path"1083done1084)10851086test -z"$modules"&&return10871088 git $diff_cmd $cached--ignore-submodules=dirty --raw$head--$modules|1089 sane_egrep '^:([0-7]* )?160000'|1090 cut -c2-|1091whileread mod_src mod_dst sha1_src sha1_dst status name1092do1093iftest -z"$cached"&&1094test$sha1_dst=00000000000000000000000000000000000000001095then1096case"$mod_dst"in1097160000)1098 sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)1099;;1100100644|100755|120000)1101 sha1_dst=$(git hash-object $name)1102;;1103000000)1104;;# removed1105*)1106# unexpected type1107 eval_gettextln "unexpected mode \$mod_dst">&21108continue;;1109esac1110fi1111 missing_src=1112 missing_dst=11131114test$mod_src=160000&&1115! GIT_DIR="$name/.git" git-rev-parse -q --verify$sha1_src^0>/dev/null &&1116 missing_src=t11171118test$mod_dst=160000&&1119! GIT_DIR="$name/.git" git-rev-parse -q --verify$sha1_dst^0>/dev/null &&1120 missing_dst=t11211122 display_name=$(relative_path "$name")11231124 total_commits=1125case"$missing_src,$missing_dst"in1126 t,)1127 errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_src")"1128;;1129,t)1130 errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_dst")"1131;;1132 t,t)1133 errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"1134;;1135*)1136 errmsg=1137 total_commits=$(1138iftest$mod_src=160000&&test$mod_dst=1600001139then1140 range="$sha1_src...$sha1_dst"1141eliftest$mod_src=1600001142then1143 range=$sha1_src1144else1145 range=$sha1_dst1146fi1147 GIT_DIR="$name/.git" \1148 git rev-list --first-parent$range--|wc-l1149)1150 total_commits=" ($(($total_commits + 0)))"1151;;1152esac11531154 sha1_abbr_src=$(echo $sha1_src | cut -c1-7)1155 sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)1156iftest$status= T1157then1158 blob="$(gettext "blob")"1159 submodule="$(gettext "submodule")"1160iftest$mod_dst=1600001161then1162echo"*$display_name$sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"1163else1164echo"*$display_name$sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"1165fi1166else1167echo"*$display_name$sha1_abbr_src...$sha1_abbr_dst$total_commits:"1168fi1169iftest -n"$errmsg"1170then1171# Don't give error msg for modification whose dst is not submodule1172# i.e. deleted or changed to blob1173test$mod_dst=160000&&echo"$errmsg"1174else1175iftest$mod_src=160000&&test$mod_dst=1600001176then1177 limit=1178test$summary_limit-gt0&& limit="-$summary_limit"1179 GIT_DIR="$name/.git" \1180 git log $limit--pretty='format: %m %s' \1181--first-parent$sha1_src...$sha1_dst1182eliftest$mod_dst=1600001183then1184 GIT_DIR="$name/.git" \1185 git log --pretty='format: > %s'-1$sha1_dst1186else1187 GIT_DIR="$name/.git" \1188 git log --pretty='format: < %s'-1$sha1_src1189fi1190echo1191fi1192echo1193done1194}1195#1196# List all submodules, prefixed with:1197# - submodule not initialized1198# + different revision checked out1199#1200# If --cached was specified the revision in the index will be printed1201# instead of the currently checked out revision.1202#1203# $@ = requested paths (default to all)1204#1205cmd_status()1206{1207# parse $args after "submodule ... status".1208whiletest$#-ne01209do1210case"$1"in1211-q|--quiet)1212 GIT_QUIET=11213;;1214--cached)1215 cached=11216;;1217--recursive)1218 recursive=11219;;1220--)1221shift1222break1223;;1224-*)1225 usage1226;;1227*)1228break1229;;1230esac1231shift1232done12331234 module_list "$@"|1235whileread mode sha1 stage sm_path1236do1237 die_if_unmatched "$mode"1238 name=$(module_name "$sm_path")||exit1239 url=$(git config submodule."$name".url)1240 displaypath=$(relative_path "$prefix$sm_path")1241iftest"$stage"= U1242then1243 say "U$sha1$displaypath"1244continue1245fi1246iftest -z"$url"||1247{1248!test -d"$sm_path"/.git &&1249!test -f"$sm_path"/.git1250}1251then1252 say "-$sha1$displaypath"1253continue;1254fi1255if git diff-files --ignore-submodules=dirty --quiet --"$sm_path"1256then1257 set_name_rev "$sm_path""$sha1"1258 say "$sha1$displaypath$revname"1259else1260iftest -z"$cached"1261then1262 sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)1263fi1264 set_name_rev "$sm_path""$sha1"1265 say "+$sha1$displaypath$revname"1266fi12671268iftest -n"$recursive"1269then1270(1271 prefix="$displaypath/"1272 clear_local_git_env1273cd"$sm_path"&&1274eval cmd_status1275) ||1276 die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"1277fi1278done1279}1280#1281# Sync remote urls for submodules1282# This makes the value for remote.$remote.url match the value1283# specified in .gitmodules.1284#1285cmd_sync()1286{1287whiletest$#-ne01288do1289case"$1"in1290-q|--quiet)1291 GIT_QUIET=11292shift1293;;1294--recursive)1295 recursive=11296shift1297;;1298--)1299shift1300break1301;;1302-*)1303 usage1304;;1305*)1306break1307;;1308esac1309done1310 cd_to_toplevel1311 module_list "$@"|1312whileread mode sha1 stage sm_path1313do1314 die_if_unmatched "$mode"1315 name=$(module_name "$sm_path")1316 url=$(git config -f .gitmodules --get submodule."$name".url)13171318# Possibly a url relative to parent1319case"$url"in1320 ./*|../*)1321# rewrite foo/bar as ../.. to find path from1322# submodule work tree to superproject work tree1323 up_path="$(printf '%s\n' "$sm_path" | sed "s/[^/][^/]*/../g")"&&1324# guarantee a trailing /1325 up_path=${up_path%/}/ &&1326# path from submodule work tree to submodule origin repo1327 sub_origin_url=$(resolve_relative_url "$url" "$up_path")&&1328# path from superproject work tree to submodule origin repo1329 super_config_url=$(resolve_relative_url "$url")||exit1330;;1331*)1332 sub_origin_url="$url"1333 super_config_url="$url"1334;;1335esac13361337if git config "submodule.$name.url">/dev/null 2>/dev/null1338then1339 displaypath=$(relative_path "$prefix$sm_path")1340 say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"1341 git config submodule."$name".url "$super_config_url"13421343iftest -e"$sm_path"/.git1344then1345(1346 clear_local_git_env1347cd"$sm_path"1348 remote=$(get_default_remote)1349 git config remote."$remote".url "$sub_origin_url"13501351iftest -n"$recursive"1352then1353 prefix="$prefix$sm_path/"1354eval cmd_sync1355fi1356)1357fi1358fi1359done1360}13611362# This loop parses the command line arguments to find the1363# subcommand name to dispatch. Parsing of the subcommand specific1364# options are primarily done by the subcommand implementations.1365# Subcommand specific options such as --branch and --cached are1366# parsed here as well, for backward compatibility.13671368whiletest$#!=0&&test -z"$command"1369do1370case"$1"in1371 add | foreach | init | deinit | update | status | summary | sync)1372command=$11373;;1374-q|--quiet)1375 GIT_QUIET=11376;;1377-b|--branch)1378case"$2"in1379'')1380 usage1381;;1382esac1383 branch="$2";shift1384;;1385--cached)1386 cached="$1"1387;;1388--)1389break1390;;1391-*)1392 usage1393;;1394*)1395break1396;;1397esac1398shift1399done14001401# No command word defaults to "status"1402iftest -z"$command"1403then1404iftest$#=01405then1406command=status1407else1408 usage1409fi1410fi14111412# "-b branch" is accepted only by "add"1413iftest -n"$branch"&&test"$command"!= add1414then1415 usage1416fi14171418# "--cached" is accepted only by "status" and "summary"1419iftest -n"$cached"&&test"$command"!= status &&test"$command"!= summary1420then1421 usage1422fi14231424"cmd_$command""$@"