git-submodule.sh 27.0 KB
Newer Older
L
Lars Hjemli 已提交
1 2
#!/bin/sh
#
3
# git-submodule.sh: add, init, update or list git submodules
L
Lars Hjemli 已提交
4 5 6
#
# Copyright (c) 2007 Lars Hjemli

7
dashless=$(basename "$0" | sed -e 's/-/ /')
8
USAGE="[--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>...]
J
Jens Lehmann 已提交
11
   or: $dashless [--quiet] deinit [-f|--force] [--] <path>...
12
   or: $dashless [--quiet] update [--init] [-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>
P
Phil Hord 已提交
15
   or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
16
OPTIONS_SPEC=
L
Lars Hjemli 已提交
17
. git-sh-setup
18
. git-sh-i18n
19
. git-parse-remote
L
Lars Hjemli 已提交
20 21
require_work_tree

22
command=
23
branch=
24
force=
25
reference=
L
Lars Hjemli 已提交
26
cached=
27 28
recursive=
init=
29
files=
30
nofetch=
31
update=
32
prefix=
33
custom_name=
L
Lars Hjemli 已提交
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
# The function takes at most 2 arguments. The first argument is the
# URL that navigates to the submodule origin repo. When relative, this URL
# is relative to the superproject origin URL repo. The second up_path
# argument, if specified, is the relative path that navigates
# from the submodule working tree to the superproject working tree.
#
# The output of the function is the origin URL of the submodule.
#
# The output will either be an absolute URL or filesystem path (if the
# superproject origin URL is an absolute URL or filesystem path,
# respectively) or a relative file system path (if the superproject
# origin URL is a relative file system path).
#
# When the output is a relative file system path, the path is either
# relative to the submodule working tree, if up_path is specified, or to
# the superproject working tree otherwise.
51 52
resolve_relative_url ()
{
53
	remote=$(get_default_remote)
54
	remoteurl=$(git config "remote.$remote.url") ||
55
		remoteurl=$(pwd) # the repository is its own authoritative upstream
56
	url="$1"
57
	remoteurl=${remoteurl%/}
58
	sep=/
59 60 61 62 63 64
	up_path="$2"

	case "$remoteurl" in
	*:*|/*)
		is_relative=
		;;
65 66 67
	./*|../*)
		is_relative=t
		;;
68 69
	*)
		is_relative=t
70
		remoteurl="./$remoteurl"
71 72 73
		;;
	esac

74 75 76 77 78
	while test -n "$url"
	do
		case "$url" in
		../*)
			url="${url#../}"
79 80 81 82 83 84 85 86 87
			case "$remoteurl" in
			*/*)
				remoteurl="${remoteurl%/*}"
				;;
			*:*)
				remoteurl="${remoteurl%:*}"
				sep=:
				;;
			*)
88 89 90 91 92 93
				if test -z "$is_relative" || test "." = "$remoteurl"
				then
					die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
				else
					remoteurl=.
				fi
94 95
				;;
			esac
96 97 98 99 100 101 102 103
			;;
		./*)
			url="${url#./}"
			;;
		*)
			break;;
		esac
	done
104 105
	remoteurl="$remoteurl$sep${url%/}"
	echo "${is_relative:+${up_path}}${remoteurl#./}"
106 107
}

108 109 110 111 112 113
#
# Get submodule info for registered submodules
# $@ = path to limit submodule list
#
module_list()
{
114 115 116 117
	(
		git ls-files --error-unmatch --stage -- "$@" ||
		echo "unmatched pathspec exists"
	) |
118 119 120
	perl -e '
	my %unmerged = ();
	my ($null_sha1) = ("0" x 40);
121 122
	my @out = ();
	my $unmatched = 0;
123
	while (<STDIN>) {
124 125 126 127
		if (/^unmatched pathspec/) {
			$unmatched = 1;
			next;
		}
128 129 130 131 132 133
		chomp;
		my ($mode, $sha1, $stage, $path) =
			/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
		next unless $mode eq "160000";
		if ($stage ne "0") {
			if (!$unmerged{$path}++) {
134
				push @out, "$mode $null_sha1 U\t$path\n";
135 136 137
			}
			next;
		}
138 139 140 141 142 143
		push @out, "$_\n";
	}
	if ($unmatched) {
		print "#unmatched\n";
	} else {
		print for (@out);
144 145
	}
	'
146 147
}

148 149 150 151 152 153 154 155
die_if_unmatched ()
{
	if test "$1" = "#unmatched"
	then
		exit 1
	fi
}

156 157 158 159 160 161 162
#
# Map submodule path to submodule name
#
# $1 = path
#
module_name()
{
163
	# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
164
	sm_path="$1"
C
Chris Ridd 已提交
165
	re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
166
	name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
167
		sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
T
Tay Ray Chuan 已提交
168
	test -z "$name" &&
169
	die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
T
Tay Ray Chuan 已提交
170
	echo "$name"
171
}
172 173 174 175

#
# Clone a submodule
#
176
# Prior to calling, cmd_update checks that a possibly existing
177
# path is not a git repository.
178
# Likewise, cmd_add checks that path does not exist at all,
179 180
# since it is the location of a new submodule.
#
181 182
module_clone()
{
183
	sm_path=$1
184 185 186
	name=$2
	url=$3
	reference="$4"
187 188 189 190 191
	quiet=
	if test -n "$GIT_QUIET"
	then
		quiet=-q
	fi
192

F
Fredrik Gustafsson 已提交
193 194
	gitdir=
	gitdir_base=
195
	base_name=$(dirname "$name")
196

F
Fredrik Gustafsson 已提交
197
	gitdir=$(git rev-parse --git-dir)
198 199
	gitdir_base="$gitdir/modules/$base_name"
	gitdir="$gitdir/modules/$name"
F
Fredrik Gustafsson 已提交
200 201

	if test -d "$gitdir"
202
	then
203
		mkdir -p "$sm_path"
F
Fredrik Gustafsson 已提交
204
		rm -f "$gitdir/index"
205
	else
F
Fredrik Gustafsson 已提交
206
		mkdir -p "$gitdir_base"
207 208 209 210 211
		(
			clear_local_git_env
			git clone $quiet -n ${reference:+"$reference"} \
				--separate-git-dir "$gitdir" "$url" "$sm_path"
		) ||
212
		die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
F
Fredrik Gustafsson 已提交
213
	fi
214

215 216 217
	# We already are at the root of the work tree but cd_to_toplevel will
	# resolve any symlinks that might be present in $PWD
	a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
218
	b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
219 220 221
	# normalize Windows-style absolute paths to POSIX-style absolute paths
	case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac
	case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac
222 223 224 225 226 227 228 229 230 231 232 233 234
	# Remove all common leading directories after a sanity check
	if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
		die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
	fi
	while test "${a%%/*}" = "${b%%/*}"
	do
		a=${a#*/}
		b=${b#*/}
	done
	# Now chop off the trailing '/'s that were added in the beginning
	a=${a%/}
	b=${b%/}

235 236
	# Turn each leading "*/" component into "../"
	rel=$(echo $b | sed -e 's|[^/][^/]*|..|g')
237
	echo "gitdir: $rel/$a" >"$sm_path/.git"
238

239
	rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
240
	(clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
241 242
}

243 244 245
#
# Add a new submodule to the working tree, .gitmodules and the index
#
246
# $@ = repo path
247 248 249
#
# optional branch is stored in global branch variable
#
250
cmd_add()
251
{
252 253 254 255 256 257 258 259 260
	# parse $args after "submodule ... add".
	while test $# -ne 0
	do
		case "$1" in
		-b | --branch)
			case "$2" in '') usage ;; esac
			branch=$2
			shift
			;;
261 262 263
		-f | --force)
			force=$1
			;;
264
		-q|--quiet)
265
			GIT_QUIET=1
266
			;;
267 268 269 270 271 272 273 274
		--reference)
			case "$2" in '') usage ;; esac
			reference="--reference=$2"
			shift
			;;
		--reference=*)
			reference="$1"
			;;
275 276 277 278 279
		--name)
			case "$2" in '') usage ;; esac
			custom_name=$2
			shift
			;;
280 281 282 283 284 285 286 287 288 289 290 291 292 293
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done

294
	repo=$1
295
	sm_path=$2
296

297 298
	if test -z "$sm_path"; then
		sm_path=$(echo "$repo" |
299 300 301
			sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
	fi

302
	if test -z "$repo" -o -z "$sm_path"; then
303 304 305
		usage
	fi

306 307 308 309 310 311 312 313 314 315 316
	# assure repo is absolute or relative to parent
	case "$repo" in
	./*|../*)
		# dereference source url relative to parent's url
		realrepo=$(resolve_relative_url "$repo") || exit
		;;
	*:*|/*)
		# absolute url
		realrepo=$repo
		;;
	*)
317
		die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
318 319 320
	;;
	esac

321 322
	# normalize path:
	# multiple //; leading ./; /./; /../; trailing /
323
	sm_path=$(printf '%s/\n' "$sm_path" |
324 325 326 327 328 329 330 331 332
		sed -e '
			s|//*|/|g
			s|^\(\./\)*||
			s|/\./|/|g
			:start
			s|\([^/]*\)/\.\./||
			tstart
			s|/*$||
		')
333 334
	git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
	die "$(eval_gettext "'\$sm_path' already exists in the index")"
335

336
	if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
337
	then
338
		eval_gettextln "The following path is ignored by one of your .gitignore files:
339
\$sm_path
340
Use -f if you really want to add it." >&2
341 342 343
		exit 1
	fi

344 345 346 347 348 349 350
	if test -n "$custom_name"
	then
		sm_name="$custom_name"
	else
		sm_name="$sm_path"
	fi

351
	# perhaps the path exists and is already a git repo, else clone it
352
	if test -e "$sm_path"
353
	then
354
		if test -d "$sm_path"/.git -o -f "$sm_path"/.git
355
		then
356
			eval_gettextln "Adding existing repo at '\$sm_path' to the index"
357
		else
358
			die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")"
359
		fi
360

361
	else
362 363 364 365 366 367 368 369 370 371 372 373 374 375
		if test -d ".git/modules/$sm_name"
		then
			if test -z "$force"
			then
				echo >&2 "$(eval_gettext "A git directory for '\$sm_name' is found locally with remote(s):")"
				GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^,"  ", -e s,' (fetch)',, >&2
				echo >&2 "$(eval_gettext "If you want to reuse this local git directory instead of cloning again from")"
				echo >&2 "  $realrepo"
				echo >&2 "$(eval_gettext "use the '--force' option. If the local git directory is not the correct repo")"
				die "$(eval_gettext "or you are unsure what this means choose another name with the '--name' option.")"
			else
				echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
			fi
		fi
376
		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" || exit
377
		(
378
			clear_local_git_env
379
			cd "$sm_path" &&
380 381 382
			# ash fails to wordsplit ${branch:+-b "$branch"...}
			case "$branch" in
			'') git checkout -f -q ;;
383
			?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
384
			esac
385
		) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
386
	fi
387
	git config submodule."$sm_name".url "$realrepo"
388

389 390
	git add $force "$sm_path" ||
	die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
391

392 393
	git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&
	git config -f .gitmodules submodule."$sm_name".url "$repo" &&
394
	git add --force .gitmodules ||
395
	die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
396 397
}

398 399 400 401 402 403 404 405
#
# Execute an arbitrary command sequence in each checked out
# submodule
#
# $@ = command to execute
#
cmd_foreach()
{
406 407 408 409 410 411 412
	# parse $args after "submodule ... foreach".
	while test $# -ne 0
	do
		case "$1" in
		-q|--quiet)
			GIT_QUIET=1
			;;
413 414 415
		--recursive)
			recursive=1
			;;
416 417 418 419 420 421 422 423 424 425
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done

426 427
	toplevel=$(pwd)

428 429 430 431
	# dup stdin so that it can be restored when running the external
	# command in the subshell (and a recursive call to this function)
	exec 3<&0

432
	module_list |
433
	while read mode sha1 stage sm_path
434
	do
435
		die_if_unmatched "$mode"
436
		if test -e "$sm_path"/.git
437
		then
438 439
			say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
			name=$(module_name "$sm_path")
440
			(
441
				prefix="$prefix$sm_path/"
442
				clear_local_git_env
443 444 445
				# we make $path available to scripts ...
				path=$sm_path
				cd "$sm_path" &&
446 447 448 449 450
				eval "$@" &&
				if test -n "$recursive"
				then
					cmd_foreach "--recursive" "$@"
				fi
451
			) <&3 3<&- ||
452
			die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
453 454 455 456
		fi
	done
}

L
Lars Hjemli 已提交
457
#
458
# Register submodules in .git/config
L
Lars Hjemli 已提交
459 460 461
#
# $@ = requested paths (default to all)
#
462
cmd_init()
L
Lars Hjemli 已提交
463
{
464 465 466 467 468
	# parse $args after "submodule ... init".
	while test $# -ne 0
	do
		case "$1" in
		-q|--quiet)
469
			GIT_QUIET=1
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
			;;
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done

485
	module_list "$@" |
486
	while read mode sha1 stage sm_path
L
Lars Hjemli 已提交
487
	do
488
		die_if_unmatched "$mode"
489
		name=$(module_name "$sm_path") || exit
490 491

		# Copy url setting when it is not set yet
492 493 494 495
		if test -z "$(git config "submodule.$name.url")"
		then
			url=$(git config -f .gitmodules submodule."$name".url)
			test -z "$url" &&
496
			die "$(eval_gettext "No url found for submodule path '\$sm_path' in .gitmodules")"
497 498 499 500 501 502 503 504

			# Possibly a url relative to parent
			case "$url" in
			./*|../*)
				url=$(resolve_relative_url "$url") || exit
				;;
			esac
			git config submodule."$name".url "$url" ||
505
			die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
506 507

			say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
508
		fi
L
Lars Hjemli 已提交
509

510
		# Copy "update" setting when it is not set yet
511 512
		upd="$(git config -f .gitmodules submodule."$name".update)"
		test -z "$upd" ||
513
		test -n "$(git config submodule."$name".update)" ||
514
		git config submodule."$name".update "$upd" ||
515
		die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
L
Lars Hjemli 已提交
516 517 518
	done
}

J
Jens Lehmann 已提交
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
#
# Unregister submodules from .git/config and remove their work tree
#
# $@ = requested paths (use '.' to deinit all submodules)
#
cmd_deinit()
{
	# parse $args after "submodule ... deinit".
	while test $# -ne 0
	do
		case "$1" in
		-f|--force)
			force=$1
			;;
		-q|--quiet)
			GIT_QUIET=1
			;;
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done

	if test $# = 0
	then
		die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
	fi

	module_list "$@" |
	while read mode sha1 stage sm_path
	do
		die_if_unmatched "$mode"
		name=$(module_name "$sm_path") || exit

		# Remove the submodule work tree (unless the user already did it)
		if test -d "$sm_path"
		then
			# Protect submodules containing a .git directory
			if test -d "$sm_path/.git"
			then
				echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
				die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
			fi

			if test -z "$force"
			then
				git rm -n "$sm_path" ||
				die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
			fi
			rm -rf "$sm_path" || say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
		fi

		mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"

		# Remove the .git/config entries (unless the user already did it)
		if test -n "$(git config --get-regexp submodule."$name\.")"
		then
			# Remove the whole section so we have a clean state when
			# the user later decides to init this submodule again
			url=$(git config submodule."$name".url)
			git config --remove-section submodule."$name" 2>/dev/null &&
			say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
		fi
	done
}

L
Lars Hjemli 已提交
593
#
594
# Update each submodule path to correct revision, using clone and checkout as needed
L
Lars Hjemli 已提交
595 596 597
#
# $@ = requested paths (default to all)
#
598
cmd_update()
L
Lars Hjemli 已提交
599
{
600
	# parse $args after "submodule ... update".
601
	orig_flags=
602 603 604 605
	while test $# -ne 0
	do
		case "$1" in
		-q|--quiet)
606
			GIT_QUIET=1
607
			;;
608
		-i|--init)
609
			init=1
610
			;;
611 612 613
		-N|--no-fetch)
			nofetch=1
			;;
614 615 616
		-f|--force)
			force=$1
			;;
617
		-r|--rebase)
618
			update="rebase"
619
			;;
620 621 622
		--reference)
			case "$2" in '') usage ;; esac
			reference="--reference=$2"
623 624
			orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
			shift
625 626 627 628
			;;
		--reference=*)
			reference="$1"
			;;
629 630 631
		-m|--merge)
			update="merge"
			;;
632 633 634
		--recursive)
			recursive=1
			;;
635 636 637
		--checkout)
			update="checkout"
			;;
638 639 640 641 642 643 644 645 646 647 648
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
649 650
		orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
		shift
651 652
	done

653 654 655 656 657
	if test -n "$init"
	then
		cmd_init "--" "$@" || return
	fi

658
	cloned_modules=
659 660
	module_list "$@" | {
	err=
661
	while read mode sha1 stage sm_path
L
Lars Hjemli 已提交
662
	do
663
		die_if_unmatched "$mode"
664 665
		if test "$stage" = U
		then
666
			echo >&2 "Skipping unmerged submodule $sm_path"
667 668
			continue
		fi
669
		name=$(module_name "$sm_path") || exit
670
		url=$(git config submodule."$name".url)
671 672 673 674 675 676 677 678 679
		if ! test -z "$update"
		then
			update_module=$update
		else
			update_module=$(git config submodule."$name".update)
		fi

		if test "$update_module" = "none"
		then
680
			echo "Skipping submodule '$sm_path'"
681 682 683
			continue
		fi

684
		if test -z "$url"
L
Lars Hjemli 已提交
685 686 687 688
		then
			# Only mention uninitialized submodules when its
			# path have been specified
			test "$#" != "0" &&
689
			say "$(eval_gettext "Submodule path '\$sm_path' not initialized
690
Maybe you want to use 'update --init'?")"
691 692 693
			continue
		fi

694
		if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
695
		then
696
			module_clone "$sm_path" "$name" "$url" "$reference" || exit
697
			cloned_modules="$cloned_modules;$name"
698 699
			subsha1=
		else
700
			subsha1=$(clear_local_git_env; cd "$sm_path" &&
701
				git rev-parse --verify HEAD) ||
702
			die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
L
Lars Hjemli 已提交
703
		fi
704

705
		if test "$subsha1" != "$sha1" -o -n "$force"
L
Lars Hjemli 已提交
706
		then
707 708 709
			subforce=$force
			# If we don't already have a -f flag and the submodule has never been checked out
			if test -z "$subsha1" -a -z "$force"
710
			then
711
				subforce="-f"
712
			fi
713 714 715

			if test -z "$nofetch"
			then
716 717
				# Run fetch only if $sha1 isn't present or it
				# is not reachable from a ref.
718
				(clear_local_git_env; cd "$sm_path" &&
719
					( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
720
					 test -z "$rev") || git-fetch)) ||
721
				die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
722 723
			fi

724 725 726 727 728 729 730
			# Is this something we just cloned?
			case ";$cloned_modules;" in
			*";$name;"*)
				# then there is no local change to integrate
				update_module= ;;
			esac

731
			must_die_on_failure=
732 733 734
			case "$update_module" in
			rebase)
				command="git rebase"
735 736
				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")"
				say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")"
737
				must_die_on_failure=yes
738
				;;
739 740
			merge)
				command="git merge"
741 742
				die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$sm_path'")"
				say_msg="$(eval_gettext "Submodule path '\$sm_path': merged in '\$sha1'")"
743
				must_die_on_failure=yes
744
				;;
745
			*)
746
				command="git checkout $subforce -q"
747 748
				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$sm_path'")"
				say_msg="$(eval_gettext "Submodule path '\$sm_path': checked out '\$sha1'")"
749 750
				;;
			esac
L
Lars Hjemli 已提交
751

752
			if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
753
			then
754
				say "$say_msg"
755 756
			elif test -n "$must_die_on_failure"
			then
757
				die_with_status 2 "$die_msg"
758
			else
759
				err="${err};$die_msg"
760
				continue
761
			fi
L
Lars Hjemli 已提交
762
		fi
763 764 765

		if test -n "$recursive"
		then
766
			(clear_local_git_env; cd "$sm_path" && eval cmd_update "$orig_flags")
767 768 769
			res=$?
			if test $res -gt 0
			then
770
				die_msg="$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
771 772
				if test $res -eq 1
				then
773
					err="${err};$die_msg"
774 775
					continue
				else
776
					die_with_status $res "$die_msg"
777 778
				fi
			fi
779
		fi
L
Lars Hjemli 已提交
780
	done
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796

	if test -n "$err"
	then
		OIFS=$IFS
		IFS=';'
		for e in $err
		do
			if test -n "$e"
			then
				echo >&2 "$e"
			fi
		done
		IFS=$OIFS
		exit 1
	fi
	}
L
Lars Hjemli 已提交
797 798
}

799 800
set_name_rev () {
	revname=$( (
801
		clear_local_git_env
802
		cd "$1" && {
803 804
			git describe "$2" 2>/dev/null ||
			git describe --tags "$2" 2>/dev/null ||
805 806
			git describe --contains "$2" 2>/dev/null ||
			git describe --all --always "$2"
807 808 809 810
		}
	) )
	test -z "$revname" || revname=" ($revname)"
}
P
Ping Yin 已提交
811 812 813 814 815 816 817 818 819
#
# Show commit summary for submodules in index or working tree
#
# If '--cached' is given, show summary between index and given commit,
# or between working tree and given commit
#
# $@ = [commit (default 'HEAD'),] requested paths (default all)
#
cmd_summary() {
820
	summary_limit=-1
821
	for_status=
822
	diff_cmd=diff-index
823

P
Ping Yin 已提交
824 825 826 827 828 829 830
	# parse $args after "submodule ... summary".
	while test $# -ne 0
	do
		case "$1" in
		--cached)
			cached="$1"
			;;
831 832 833
		--files)
			files="$1"
			;;
834 835 836
		--for-status)
			for_status="$1"
			;;
837 838 839 840 841 842 843 844 845
		-n|--summary-limit)
			if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
			then
				:
			else
				usage
			fi
			shift
			;;
P
Ping Yin 已提交
846 847 848 849 850 851 852 853 854 855 856 857 858
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done
859

860 861
	test $summary_limit = 0 && return

862
	if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
P
Ping Yin 已提交
863 864
	then
		head=$rev
865
		test $# = 0 || shift
866 867
	elif test -z "$1" -o "$1" = "HEAD"
	then
868 869
		# before the first commit: compare with an empty tree
		head=$(git hash-object -w -t tree --stdin </dev/null)
870
		test -z "$1" || shift
P
Ping Yin 已提交
871
	else
872
		head="HEAD"
P
Ping Yin 已提交
873 874
	fi

875 876 877
	if [ -n "$files" ]
	then
		test -n "$cached" &&
878
		die "$(gettext "The --cached option cannot be used with the --files option")"
879 880 881 882
		diff_cmd=diff-files
		head=
	fi

P
Ping Yin 已提交
883 884
	cd_to_toplevel
	# Get modified modules cared by user
885
	modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
886
		sane_egrep '^:([0-7]* )?160000' |
P
Ping Yin 已提交
887 888 889 890 891 892 893 894 895
		while read mod_src mod_dst sha1_src sha1_dst status name
		do
			# Always show modules deleted or type-changed (blob<->module)
			test $status = D -o $status = T && echo "$name" && continue
			# Also show added or modified modules which are checked out
			GIT_DIR="$name/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
			echo "$name"
		done
	)
896

897 898
	test -z "$modules" && return

899
	git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
900
	sane_egrep '^:([0-7]* )?160000' |
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
	cut -c2- |
	while read mod_src mod_dst sha1_src sha1_dst status name
	do
		if test -z "$cached" &&
			test $sha1_dst = 0000000000000000000000000000000000000000
		then
			case "$mod_dst" in
			160000)
				sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
				;;
			100644 | 100755 | 120000)
				sha1_dst=$(git hash-object $name)
				;;
			000000)
				;; # removed
			*)
				# unexpected type
918
				eval_gettextln "unexpected mode \$mod_dst" >&2
919 920 921 922 923 924 925
				continue ;;
			esac
		fi
		missing_src=
		missing_dst=

		test $mod_src = 160000 &&
M
Miklos Vajna 已提交
926
		! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
927 928 929
		missing_src=t

		test $mod_dst = 160000 &&
M
Miklos Vajna 已提交
930
		! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
931
		missing_dst=t
932

933 934 935
		total_commits=
		case "$missing_src,$missing_dst" in
		t,)
936
			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_src")"
937 938
			;;
		,t)
939
			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_dst")"
940 941
			;;
		t,t)
942
			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
943 944 945 946 947 948 949 950 951 952 953 954 955 956
			;;
		*)
			errmsg=
			total_commits=$(
			if test $mod_src = 160000 -a $mod_dst = 160000
			then
				range="$sha1_src...$sha1_dst"
			elif test $mod_src = 160000
			then
				range=$sha1_src
			else
				range=$sha1_dst
			fi
			GIT_DIR="$name/.git" \
J
Jeff King 已提交
957
			git rev-list --first-parent $range -- | wc -l
958
			)
959
			total_commits=" ($(($total_commits + 0)))"
960 961 962 963 964 965 966
			;;
		esac

		sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
		sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
		if test $status = T
		then
967 968
			blob="$(gettext "blob")"
			submodule="$(gettext "submodule")"
969 970
			if test $mod_dst = 160000
			then
971
				echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
972
			else
973
				echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
974 975 976 977 978 979 980 981 982 983 984 985
			fi
		else
			echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
		fi
		if test -n "$errmsg"
		then
			# Don't give error msg for modification whose dst is not submodule
			# i.e. deleted or changed to blob
			test $mod_dst = 160000 && echo "$errmsg"
		else
			if test $mod_src = 160000 -a $mod_dst = 160000
			then
986 987
				limit=
				test $summary_limit -gt 0 && limit="-$summary_limit"
988
				GIT_DIR="$name/.git" \
989
				git log $limit --pretty='format:  %m %s' \
990 991 992 993 994 995 996 997 998 999 1000 1001
				--first-parent $sha1_src...$sha1_dst
			elif test $mod_dst = 160000
			then
				GIT_DIR="$name/.git" \
				git log --pretty='format:  > %s' -1 $sha1_dst
			else
				GIT_DIR="$name/.git" \
				git log --pretty='format:  < %s' -1 $sha1_src
			fi
			echo
		fi
		echo
1002 1003
	done |
	if test -n "$for_status"; then
1004
		if [ -n "$files" ]; then
1005
			gettextln "# Submodules changed but not updated:"
1006
		else
1007
			gettextln "# Submodule changes to be committed:"
1008
		fi
1009 1010 1011 1012 1013
		echo "#"
		sed -e 's|^|# |' -e 's|^# $|#|'
	else
		cat
	fi
P
Ping Yin 已提交
1014
}
L
Lars Hjemli 已提交
1015
#
1016
# List all submodules, prefixed with:
L
Lars Hjemli 已提交
1017 1018 1019 1020 1021 1022 1023 1024
#  - submodule not initialized
#  + different revision checked out
#
# If --cached was specified the revision in the index will be printed
# instead of the currently checked out revision.
#
# $@ = requested paths (default to all)
#
1025
cmd_status()
L
Lars Hjemli 已提交
1026
{
1027 1028 1029 1030 1031
	# parse $args after "submodule ... status".
	while test $# -ne 0
	do
		case "$1" in
		-q|--quiet)
1032
			GIT_QUIET=1
1033 1034 1035 1036
			;;
		--cached)
			cached=1
			;;
1037 1038 1039
		--recursive)
			recursive=1
			;;
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
		shift
	done

1054
	module_list "$@" |
1055
	while read mode sha1 stage sm_path
L
Lars Hjemli 已提交
1056
	do
1057
		die_if_unmatched "$mode"
1058
		name=$(module_name "$sm_path") || exit
1059
		url=$(git config submodule."$name".url)
1060
		displaypath="$prefix$sm_path"
1061 1062 1063 1064 1065
		if test "$stage" = U
		then
			say "U$sha1 $displaypath"
			continue
		fi
1066
		if test -z "$url" || ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
L
Lars Hjemli 已提交
1067
		then
1068
			say "-$sha1 $displaypath"
L
Lars Hjemli 已提交
1069 1070
			continue;
		fi
1071 1072
		set_name_rev "$sm_path" "$sha1"
		if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
L
Lars Hjemli 已提交
1073
		then
1074
			say " $sha1 $displaypath$revname"
L
Lars Hjemli 已提交
1075 1076 1077
		else
			if test -z "$cached"
			then
1078 1079
				sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
				set_name_rev "$sm_path" "$sha1"
L
Lars Hjemli 已提交
1080
			fi
1081 1082 1083 1084 1085 1086 1087
			say "+$sha1 $displaypath$revname"
		fi

		if test -n "$recursive"
		then
			(
				prefix="$displaypath/"
1088
				clear_local_git_env
1089
				cd "$sm_path" &&
1090
				eval cmd_status
1091
			) ||
1092
			die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
L
Lars Hjemli 已提交
1093 1094 1095
		fi
	done
}
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
#
# Sync remote urls for submodules
# This makes the value for remote.$remote.url match the value
# specified in .gitmodules.
#
cmd_sync()
{
	while test $# -ne 0
	do
		case "$1" in
		-q|--quiet)
1107
			GIT_QUIET=1
1108 1109
			shift
			;;
P
Phil Hord 已提交
1110 1111 1112 1113
		--recursive)
			recursive=1
			shift
			;;
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
		--)
			shift
			break
			;;
		-*)
			usage
			;;
		*)
			break
			;;
		esac
	done
	cd_to_toplevel
	module_list "$@" |
1128
	while read mode sha1 stage sm_path
1129
	do
1130
		die_if_unmatched "$mode"
1131
		name=$(module_name "$sm_path")
1132
		url=$(git config -f .gitmodules --get submodule."$name".url)
1133 1134 1135 1136

		# Possibly a url relative to parent
		case "$url" in
		./*|../*)
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
			# rewrite foo/bar as ../.. to find path from
			# submodule work tree to superproject work tree
			up_path="$(echo "$sm_path" | sed "s/[^/][^/]*/../g")" &&
			# guarantee a trailing /
			up_path=${up_path%/}/ &&
			# path from submodule work tree to submodule origin repo
			sub_origin_url=$(resolve_relative_url "$url" "$up_path") &&
			# path from superproject work tree to submodule origin repo
			super_config_url=$(resolve_relative_url "$url") || exit
			;;
		*)
			sub_origin_url="$url"
			super_config_url="$url"
1150 1151 1152
			;;
		esac

1153
		if git config "submodule.$name.url" >/dev/null 2>/dev/null
1154
		then
P
Phil Hord 已提交
1155
			say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
1156
			git config submodule."$name".url "$super_config_url"
1157

1158
			if test -e "$sm_path"/.git
1159 1160 1161
			then
			(
				clear_local_git_env
1162
				cd "$sm_path"
1163
				remote=$(get_default_remote)
1164
				git config remote."$remote".url "$sub_origin_url"
P
Phil Hord 已提交
1165 1166 1167 1168 1169 1170

				if test -n "$recursive"
				then
					prefix="$prefix$sm_path/"
					eval cmd_sync
				fi
1171 1172
			)
			fi
1173 1174 1175
		fi
	done
}
L
Lars Hjemli 已提交
1176

1177 1178 1179 1180 1181 1182 1183
# This loop parses the command line arguments to find the
# subcommand name to dispatch.  Parsing of the subcommand specific
# options are primarily done by the subcommand implementations.
# Subcommand specific options such as --branch and --cached are
# parsed here as well, for backward compatibility.

while test $# != 0 && test -z "$command"
L
Lars Hjemli 已提交
1184 1185
do
	case "$1" in
J
Jens Lehmann 已提交
1186
	add | foreach | init | deinit | update | status | summary | sync)
1187
		command=$1
L
Lars Hjemli 已提交
1188 1189
		;;
	-q|--quiet)
1190
		GIT_QUIET=1
L
Lars Hjemli 已提交
1191
		;;
1192 1193 1194 1195 1196 1197 1198 1199
	-b|--branch)
		case "$2" in
		'')
			usage
			;;
		esac
		branch="$2"; shift
		;;
L
Lars Hjemli 已提交
1200
	--cached)
P
Ping Yin 已提交
1201
		cached="$1"
L
Lars Hjemli 已提交
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
		;;
	--)
		break
		;;
	-*)
		usage
		;;
	*)
		break
		;;
	esac
	shift
done

1216
# No command word defaults to "status"
1217 1218 1219 1220 1221 1222 1223 1224 1225
if test -z "$command"
then
    if test $# = 0
    then
	command=status
    else
	usage
    fi
fi
1226 1227 1228 1229

# "-b branch" is accepted only by "add"
if test -n "$branch" && test "$command" != add
then
1230
	usage
1231 1232
fi

P
Ping Yin 已提交
1233 1234
# "--cached" is accepted only by "status" and "summary"
if test -n "$cached" && test "$command" != status -a "$command" != summary
1235
then
L
Lars Hjemli 已提交
1236
	usage
1237 1238 1239
fi

"cmd_$command" "$@"