Imported Upstream version 1.7.10.4
[platform/upstream/git.git] / git-submodule.sh
1 #!/bin/sh
2 #
3 # git-submodules.sh: add, init, update or list git submodules
4 #
5 # Copyright (c) 2007 Lars Hjemli
6
7 dashless=$(basename "$0" | sed -e 's/-/ /')
8 USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
9    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
10    or: $dashless [--quiet] init [--] [<path>...]
11    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
12    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
13    or: $dashless [--quiet] foreach [--recursive] <command>
14    or: $dashless [--quiet] sync [--] [<path>...]"
15 OPTIONS_SPEC=
16 . git-sh-setup
17 . git-sh-i18n
18 . git-parse-remote
19 require_work_tree
20
21 command=
22 branch=
23 force=
24 reference=
25 cached=
26 recursive=
27 init=
28 files=
29 nofetch=
30 update=
31 prefix=
32
33 # Resolve relative url by appending to parent's url
34 resolve_relative_url ()
35 {
36         remote=$(get_default_remote)
37         remoteurl=$(git config "remote.$remote.url") ||
38                 remoteurl=$(pwd) # the repository is its own authoritative upstream
39         url="$1"
40         remoteurl=${remoteurl%/}
41         sep=/
42         while test -n "$url"
43         do
44                 case "$url" in
45                 ../*)
46                         url="${url#../}"
47                         case "$remoteurl" in
48                         */*)
49                                 remoteurl="${remoteurl%/*}"
50                                 ;;
51                         *:*)
52                                 remoteurl="${remoteurl%:*}"
53                                 sep=:
54                                 ;;
55                         *)
56                                 die "$(eval_gettext "cannot strip one component off url '\$remoteurl'")"
57                                 ;;
58                         esac
59                         ;;
60                 ./*)
61                         url="${url#./}"
62                         ;;
63                 *)
64                         break;;
65                 esac
66         done
67         echo "$remoteurl$sep${url%/}"
68 }
69
70 #
71 # Get submodule info for registered submodules
72 # $@ = path to limit submodule list
73 #
74 module_list()
75 {
76         git ls-files --error-unmatch --stage -- "$@" |
77         perl -e '
78         my %unmerged = ();
79         my ($null_sha1) = ("0" x 40);
80         while (<STDIN>) {
81                 chomp;
82                 my ($mode, $sha1, $stage, $path) =
83                         /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
84                 next unless $mode eq "160000";
85                 if ($stage ne "0") {
86                         if (!$unmerged{$path}++) {
87                                 print "$mode $null_sha1 U\t$path\n";
88                         }
89                         next;
90                 }
91                 print "$_\n";
92         }
93         '
94 }
95
96 #
97 # Map submodule path to submodule name
98 #
99 # $1 = path
100 #
101 module_name()
102 {
103         # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
104         re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
105         name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
106                 sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
107         test -z "$name" &&
108         die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$path'")"
109         echo "$name"
110 }
111
112 #
113 # Clone a submodule
114 #
115 # Prior to calling, cmd_update checks that a possibly existing
116 # path is not a git repository.
117 # Likewise, cmd_add checks that path does not exist at all,
118 # since it is the location of a new submodule.
119 #
120 module_clone()
121 {
122         path=$1
123         url=$2
124         reference="$3"
125         quiet=
126         if test -n "$GIT_QUIET"
127         then
128                 quiet=-q
129         fi
130
131         gitdir=
132         gitdir_base=
133         name=$(module_name "$path" 2>/dev/null)
134         test -n "$name" || name="$path"
135         base_name=$(dirname "$name")
136
137         gitdir=$(git rev-parse --git-dir)
138         gitdir_base="$gitdir/modules/$base_name"
139         gitdir="$gitdir/modules/$name"
140
141         if test -d "$gitdir"
142         then
143                 mkdir -p "$path"
144                 rm -f "$gitdir/index"
145         else
146                 mkdir -p "$gitdir_base"
147                 git clone $quiet -n ${reference:+"$reference"} \
148                         --separate-git-dir "$gitdir" "$url" "$path" ||
149                 die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
150         fi
151
152         a=$(cd "$gitdir" && pwd)/
153         b=$(cd "$path" && pwd)/
154         # normalize Windows-style absolute paths to POSIX-style absolute paths
155         case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac
156         case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac
157         # Remove all common leading directories after a sanity check
158         if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
159                 die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
160         fi
161         while test "${a%%/*}" = "${b%%/*}"
162         do
163                 a=${a#*/}
164                 b=${b#*/}
165         done
166         # Now chop off the trailing '/'s that were added in the beginning
167         a=${a%/}
168         b=${b%/}
169
170         # Turn each leading "*/" component into "../"
171         rel=$(echo $b | sed -e 's|[^/][^/]*|..|g')
172         echo "gitdir: $rel/$a" >"$path/.git"
173
174         rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
175         (clear_local_git_env; cd "$path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
176 }
177
178 #
179 # Add a new submodule to the working tree, .gitmodules and the index
180 #
181 # $@ = repo path
182 #
183 # optional branch is stored in global branch variable
184 #
185 cmd_add()
186 {
187         # parse $args after "submodule ... add".
188         while test $# -ne 0
189         do
190                 case "$1" in
191                 -b | --branch)
192                         case "$2" in '') usage ;; esac
193                         branch=$2
194                         shift
195                         ;;
196                 -f | --force)
197                         force=$1
198                         ;;
199                 -q|--quiet)
200                         GIT_QUIET=1
201                         ;;
202                 --reference)
203                         case "$2" in '') usage ;; esac
204                         reference="--reference=$2"
205                         shift
206                         ;;
207                 --reference=*)
208                         reference="$1"
209                         shift
210                         ;;
211                 --)
212                         shift
213                         break
214                         ;;
215                 -*)
216                         usage
217                         ;;
218                 *)
219                         break
220                         ;;
221                 esac
222                 shift
223         done
224
225         repo=$1
226         path=$2
227
228         if test -z "$path"; then
229                 path=$(echo "$repo" |
230                         sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
231         fi
232
233         if test -z "$repo" -o -z "$path"; then
234                 usage
235         fi
236
237         # assure repo is absolute or relative to parent
238         case "$repo" in
239         ./*|../*)
240                 # dereference source url relative to parent's url
241                 realrepo=$(resolve_relative_url "$repo") || exit
242                 ;;
243         *:*|/*)
244                 # absolute url
245                 realrepo=$repo
246                 ;;
247         *)
248                 die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
249         ;;
250         esac
251
252         # normalize path:
253         # multiple //; leading ./; /./; /../; trailing /
254         path=$(printf '%s/\n' "$path" |
255                 sed -e '
256                         s|//*|/|g
257                         s|^\(\./\)*||
258                         s|/\./|/|g
259                         :start
260                         s|\([^/]*\)/\.\./||
261                         tstart
262                         s|/*$||
263                 ')
264         git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
265         die "$(eval_gettext "'\$path' already exists in the index")"
266
267         if test -z "$force" && ! git add --dry-run --ignore-missing "$path" > /dev/null 2>&1
268         then
269                 eval_gettextln "The following path is ignored by one of your .gitignore files:
270 \$path
271 Use -f if you really want to add it." >&2
272                 exit 1
273         fi
274
275         # perhaps the path exists and is already a git repo, else clone it
276         if test -e "$path"
277         then
278                 if test -d "$path"/.git -o -f "$path"/.git
279                 then
280                         eval_gettextln "Adding existing repo at '\$path' to the index"
281                 else
282                         die "$(eval_gettext "'\$path' already exists and is not a valid git repo")"
283                 fi
284
285         else
286
287                 module_clone "$path" "$realrepo" "$reference" || exit
288                 (
289                         clear_local_git_env
290                         cd "$path" &&
291                         # ash fails to wordsplit ${branch:+-b "$branch"...}
292                         case "$branch" in
293                         '') git checkout -f -q ;;
294                         ?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
295                         esac
296                 ) || die "$(eval_gettext "Unable to checkout submodule '\$path'")"
297         fi
298         git config submodule."$path".url "$realrepo"
299
300         git add $force "$path" ||
301         die "$(eval_gettext "Failed to add submodule '\$path'")"
302
303         git config -f .gitmodules submodule."$path".path "$path" &&
304         git config -f .gitmodules submodule."$path".url "$repo" &&
305         git add --force .gitmodules ||
306         die "$(eval_gettext "Failed to register submodule '\$path'")"
307 }
308
309 #
310 # Execute an arbitrary command sequence in each checked out
311 # submodule
312 #
313 # $@ = command to execute
314 #
315 cmd_foreach()
316 {
317         # parse $args after "submodule ... foreach".
318         while test $# -ne 0
319         do
320                 case "$1" in
321                 -q|--quiet)
322                         GIT_QUIET=1
323                         ;;
324                 --recursive)
325                         recursive=1
326                         ;;
327                 -*)
328                         usage
329                         ;;
330                 *)
331                         break
332                         ;;
333                 esac
334                 shift
335         done
336
337         toplevel=$(pwd)
338
339         # dup stdin so that it can be restored when running the external
340         # command in the subshell (and a recursive call to this function)
341         exec 3<&0
342
343         module_list |
344         while read mode sha1 stage path
345         do
346                 if test -e "$path"/.git
347                 then
348                         say "$(eval_gettext "Entering '\$prefix\$path'")"
349                         name=$(module_name "$path")
350                         (
351                                 prefix="$prefix$path/"
352                                 clear_local_git_env
353                                 cd "$path" &&
354                                 eval "$@" &&
355                                 if test -n "$recursive"
356                                 then
357                                         cmd_foreach "--recursive" "$@"
358                                 fi
359                         ) <&3 3<&- ||
360                         die "$(eval_gettext "Stopping at '\$path'; script returned non-zero status.")"
361                 fi
362         done
363 }
364
365 #
366 # Register submodules in .git/config
367 #
368 # $@ = requested paths (default to all)
369 #
370 cmd_init()
371 {
372         # parse $args after "submodule ... init".
373         while test $# -ne 0
374         do
375                 case "$1" in
376                 -q|--quiet)
377                         GIT_QUIET=1
378                         ;;
379                 --)
380                         shift
381                         break
382                         ;;
383                 -*)
384                         usage
385                         ;;
386                 *)
387                         break
388                         ;;
389                 esac
390                 shift
391         done
392
393         module_list "$@" |
394         while read mode sha1 stage path
395         do
396                 # Skip already registered paths
397                 name=$(module_name "$path") || exit
398                 if test -z "$(git config "submodule.$name.url")"
399                 then
400                         url=$(git config -f .gitmodules submodule."$name".url)
401                         test -z "$url" &&
402                         die "$(eval_gettext "No url found for submodule path '\$path' in .gitmodules")"
403
404                         # Possibly a url relative to parent
405                         case "$url" in
406                         ./*|../*)
407                                 url=$(resolve_relative_url "$url") || exit
408                                 ;;
409                         esac
410                         git config submodule."$name".url "$url" ||
411                         die "$(eval_gettext "Failed to register url for submodule path '\$path'")"
412                 fi
413
414                 # Copy "update" setting when it is not set yet
415                 upd="$(git config -f .gitmodules submodule."$name".update)"
416                 test -z "$upd" ||
417                 test -n "$(git config submodule."$name".update)" ||
418                 git config submodule."$name".update "$upd" ||
419                 die "$(eval_gettext "Failed to register update mode for submodule path '\$path'")"
420
421                 say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$path'")"
422         done
423 }
424
425 #
426 # Update each submodule path to correct revision, using clone and checkout as needed
427 #
428 # $@ = requested paths (default to all)
429 #
430 cmd_update()
431 {
432         # parse $args after "submodule ... update".
433         orig_flags=
434         while test $# -ne 0
435         do
436                 case "$1" in
437                 -q|--quiet)
438                         GIT_QUIET=1
439                         ;;
440                 -i|--init)
441                         init=1
442                         ;;
443                 -N|--no-fetch)
444                         nofetch=1
445                         ;;
446                 -f|--force)
447                         force=$1
448                         ;;
449                 -r|--rebase)
450                         update="rebase"
451                         ;;
452                 --reference)
453                         case "$2" in '') usage ;; esac
454                         reference="--reference=$2"
455                         orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
456                         shift
457                         ;;
458                 --reference=*)
459                         reference="$1"
460                         ;;
461                 -m|--merge)
462                         update="merge"
463                         ;;
464                 --recursive)
465                         recursive=1
466                         ;;
467                 --checkout)
468                         update="checkout"
469                         ;;
470                 --)
471                         shift
472                         break
473                         ;;
474                 -*)
475                         usage
476                         ;;
477                 *)
478                         break
479                         ;;
480                 esac
481                 orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
482                 shift
483         done
484
485         if test -n "$init"
486         then
487                 cmd_init "--" "$@" || return
488         fi
489
490         cloned_modules=
491         module_list "$@" | {
492         err=
493         while read mode sha1 stage path
494         do
495                 if test "$stage" = U
496                 then
497                         echo >&2 "Skipping unmerged submodule $path"
498                         continue
499                 fi
500                 name=$(module_name "$path") || exit
501                 url=$(git config submodule."$name".url)
502                 if ! test -z "$update"
503                 then
504                         update_module=$update
505                 else
506                         update_module=$(git config submodule."$name".update)
507                 fi
508
509                 if test "$update_module" = "none"
510                 then
511                         echo "Skipping submodule '$path'"
512                         continue
513                 fi
514
515                 if test -z "$url"
516                 then
517                         # Only mention uninitialized submodules when its
518                         # path have been specified
519                         test "$#" != "0" &&
520                         say "$(eval_gettext "Submodule path '\$path' not initialized
521 Maybe you want to use 'update --init'?")"
522                         continue
523                 fi
524
525                 if ! test -d "$path"/.git -o -f "$path"/.git
526                 then
527                         module_clone "$path" "$url" "$reference"|| exit
528                         cloned_modules="$cloned_modules;$name"
529                         subsha1=
530                 else
531                         subsha1=$(clear_local_git_env; cd "$path" &&
532                                 git rev-parse --verify HEAD) ||
533                         die "$(eval_gettext "Unable to find current revision in submodule path '\$path'")"
534                 fi
535
536                 if test "$subsha1" != "$sha1"
537                 then
538                         subforce=$force
539                         # If we don't already have a -f flag and the submodule has never been checked out
540                         if test -z "$subsha1" -a -z "$force"
541                         then
542                                 subforce="-f"
543                         fi
544
545                         if test -z "$nofetch"
546                         then
547                                 # Run fetch only if $sha1 isn't present or it
548                                 # is not reachable from a ref.
549                                 (clear_local_git_env; cd "$path" &&
550                                         ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
551                                          test -z "$rev") || git-fetch)) ||
552                                 die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
553                         fi
554
555                         # Is this something we just cloned?
556                         case ";$cloned_modules;" in
557                         *";$name;"*)
558                                 # then there is no local change to integrate
559                                 update_module= ;;
560                         esac
561
562                         must_die_on_failure=
563                         case "$update_module" in
564                         rebase)
565                                 command="git rebase"
566                                 die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$path'")"
567                                 say_msg="$(eval_gettext "Submodule path '\$path': rebased into '\$sha1'")"
568                                 must_die_on_failure=yes
569                                 ;;
570                         merge)
571                                 command="git merge"
572                                 die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$path'")"
573                                 say_msg="$(eval_gettext "Submodule path '\$path': merged in '\$sha1'")"
574                                 must_die_on_failure=yes
575                                 ;;
576                         *)
577                                 command="git checkout $subforce -q"
578                                 die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$path'")"
579                                 say_msg="$(eval_gettext "Submodule path '\$path': checked out '\$sha1'")"
580                                 ;;
581                         esac
582
583                         if (clear_local_git_env; cd "$path" && $command "$sha1")
584                         then
585                                 say "$say_msg"
586                         elif test -n "$must_die_on_failure"
587                         then
588                                 die_with_status 2 "$die_msg"
589                         else
590                                 err="${err};$die_msg"
591                                 continue
592                         fi
593                 fi
594
595                 if test -n "$recursive"
596                 then
597                         (clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags")
598                         res=$?
599                         if test $res -gt 0
600                         then
601                                 die_msg="$(eval_gettext "Failed to recurse into submodule path '\$path'")"
602                                 if test $res -eq 1
603                                 then
604                                         err="${err};$die_msg"
605                                         continue
606                                 else
607                                         die_with_status $res "$die_msg"
608                                 fi
609                         fi
610                 fi
611         done
612
613         if test -n "$err"
614         then
615                 OIFS=$IFS
616                 IFS=';'
617                 for e in $err
618                 do
619                         if test -n "$e"
620                         then
621                                 echo >&2 "$e"
622                         fi
623                 done
624                 IFS=$OIFS
625                 exit 1
626         fi
627         }
628 }
629
630 set_name_rev () {
631         revname=$( (
632                 clear_local_git_env
633                 cd "$1" && {
634                         git describe "$2" 2>/dev/null ||
635                         git describe --tags "$2" 2>/dev/null ||
636                         git describe --contains "$2" 2>/dev/null ||
637                         git describe --all --always "$2"
638                 }
639         ) )
640         test -z "$revname" || revname=" ($revname)"
641 }
642 #
643 # Show commit summary for submodules in index or working tree
644 #
645 # If '--cached' is given, show summary between index and given commit,
646 # or between working tree and given commit
647 #
648 # $@ = [commit (default 'HEAD'),] requested paths (default all)
649 #
650 cmd_summary() {
651         summary_limit=-1
652         for_status=
653         diff_cmd=diff-index
654
655         # parse $args after "submodule ... summary".
656         while test $# -ne 0
657         do
658                 case "$1" in
659                 --cached)
660                         cached="$1"
661                         ;;
662                 --files)
663                         files="$1"
664                         ;;
665                 --for-status)
666                         for_status="$1"
667                         ;;
668                 -n|--summary-limit)
669                         if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
670                         then
671                                 :
672                         else
673                                 usage
674                         fi
675                         shift
676                         ;;
677                 --)
678                         shift
679                         break
680                         ;;
681                 -*)
682                         usage
683                         ;;
684                 *)
685                         break
686                         ;;
687                 esac
688                 shift
689         done
690
691         test $summary_limit = 0 && return
692
693         if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
694         then
695                 head=$rev
696                 test $# = 0 || shift
697         elif test -z "$1" -o "$1" = "HEAD"
698         then
699                 # before the first commit: compare with an empty tree
700                 head=$(git hash-object -w -t tree --stdin </dev/null)
701                 test -z "$1" || shift
702         else
703                 head="HEAD"
704         fi
705
706         if [ -n "$files" ]
707         then
708                 test -n "$cached" &&
709                 die "$(gettext -- "--cached cannot be used with --files")"
710                 diff_cmd=diff-files
711                 head=
712         fi
713
714         cd_to_toplevel
715         # Get modified modules cared by user
716         modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
717                 sane_egrep '^:([0-7]* )?160000' |
718                 while read mod_src mod_dst sha1_src sha1_dst status name
719                 do
720                         # Always show modules deleted or type-changed (blob<->module)
721                         test $status = D -o $status = T && echo "$name" && continue
722                         # Also show added or modified modules which are checked out
723                         GIT_DIR="$name/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
724                         echo "$name"
725                 done
726         )
727
728         test -z "$modules" && return
729
730         git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
731         sane_egrep '^:([0-7]* )?160000' |
732         cut -c2- |
733         while read mod_src mod_dst sha1_src sha1_dst status name
734         do
735                 if test -z "$cached" &&
736                         test $sha1_dst = 0000000000000000000000000000000000000000
737                 then
738                         case "$mod_dst" in
739                         160000)
740                                 sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
741                                 ;;
742                         100644 | 100755 | 120000)
743                                 sha1_dst=$(git hash-object $name)
744                                 ;;
745                         000000)
746                                 ;; # removed
747                         *)
748                                 # unexpected type
749                                 eval_gettextln "unexpected mode \$mod_dst" >&2
750                                 continue ;;
751                         esac
752                 fi
753                 missing_src=
754                 missing_dst=
755
756                 test $mod_src = 160000 &&
757                 ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
758                 missing_src=t
759
760                 test $mod_dst = 160000 &&
761                 ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
762                 missing_dst=t
763
764                 total_commits=
765                 case "$missing_src,$missing_dst" in
766                 t,)
767                         errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_src")"
768                         ;;
769                 ,t)
770                         errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_dst")"
771                         ;;
772                 t,t)
773                         errmsg="$(eval_gettext "  Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
774                         ;;
775                 *)
776                         errmsg=
777                         total_commits=$(
778                         if test $mod_src = 160000 -a $mod_dst = 160000
779                         then
780                                 range="$sha1_src...$sha1_dst"
781                         elif test $mod_src = 160000
782                         then
783                                 range=$sha1_src
784                         else
785                                 range=$sha1_dst
786                         fi
787                         GIT_DIR="$name/.git" \
788                         git rev-list --first-parent $range -- | wc -l
789                         )
790                         total_commits=" ($(($total_commits + 0)))"
791                         ;;
792                 esac
793
794                 sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
795                 sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
796                 if test $status = T
797                 then
798                         blob="$(gettext "blob")"
799                         submodule="$(gettext "submodule")"
800                         if test $mod_dst = 160000
801                         then
802                                 echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
803                         else
804                                 echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
805                         fi
806                 else
807                         echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
808                 fi
809                 if test -n "$errmsg"
810                 then
811                         # Don't give error msg for modification whose dst is not submodule
812                         # i.e. deleted or changed to blob
813                         test $mod_dst = 160000 && echo "$errmsg"
814                 else
815                         if test $mod_src = 160000 -a $mod_dst = 160000
816                         then
817                                 limit=
818                                 test $summary_limit -gt 0 && limit="-$summary_limit"
819                                 GIT_DIR="$name/.git" \
820                                 git log $limit --pretty='format:  %m %s' \
821                                 --first-parent $sha1_src...$sha1_dst
822                         elif test $mod_dst = 160000
823                         then
824                                 GIT_DIR="$name/.git" \
825                                 git log --pretty='format:  > %s' -1 $sha1_dst
826                         else
827                                 GIT_DIR="$name/.git" \
828                                 git log --pretty='format:  < %s' -1 $sha1_src
829                         fi
830                         echo
831                 fi
832                 echo
833         done |
834         if test -n "$for_status"; then
835                 if [ -n "$files" ]; then
836                         gettextln "# Submodules changed but not updated:"
837                 else
838                         gettextln "# Submodule changes to be committed:"
839                 fi
840                 echo "#"
841                 sed -e 's|^|# |' -e 's|^# $|#|'
842         else
843                 cat
844         fi
845 }
846 #
847 # List all submodules, prefixed with:
848 #  - submodule not initialized
849 #  + different revision checked out
850 #
851 # If --cached was specified the revision in the index will be printed
852 # instead of the currently checked out revision.
853 #
854 # $@ = requested paths (default to all)
855 #
856 cmd_status()
857 {
858         # parse $args after "submodule ... status".
859         orig_flags=
860         while test $# -ne 0
861         do
862                 case "$1" in
863                 -q|--quiet)
864                         GIT_QUIET=1
865                         ;;
866                 --cached)
867                         cached=1
868                         ;;
869                 --recursive)
870                         recursive=1
871                         ;;
872                 --)
873                         shift
874                         break
875                         ;;
876                 -*)
877                         usage
878                         ;;
879                 *)
880                         break
881                         ;;
882                 esac
883                 orig_flags="$orig_flags $(git rev-parse --sq-quote "$1")"
884                 shift
885         done
886
887         module_list "$@" |
888         while read mode sha1 stage path
889         do
890                 name=$(module_name "$path") || exit
891                 url=$(git config submodule."$name".url)
892                 displaypath="$prefix$path"
893                 if test "$stage" = U
894                 then
895                         say "U$sha1 $displaypath"
896                         continue
897                 fi
898                 if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
899                 then
900                         say "-$sha1 $displaypath"
901                         continue;
902                 fi
903                 set_name_rev "$path" "$sha1"
904                 if git diff-files --ignore-submodules=dirty --quiet -- "$path"
905                 then
906                         say " $sha1 $displaypath$revname"
907                 else
908                         if test -z "$cached"
909                         then
910                                 sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
911                                 set_name_rev "$path" "$sha1"
912                         fi
913                         say "+$sha1 $displaypath$revname"
914                 fi
915
916                 if test -n "$recursive"
917                 then
918                         (
919                                 prefix="$displaypath/"
920                                 clear_local_git_env
921                                 cd "$path" &&
922                                 eval cmd_status "$orig_args"
923                         ) ||
924                         die "$(eval_gettext "Failed to recurse into submodule path '\$path'")"
925                 fi
926         done
927 }
928 #
929 # Sync remote urls for submodules
930 # This makes the value for remote.$remote.url match the value
931 # specified in .gitmodules.
932 #
933 cmd_sync()
934 {
935         while test $# -ne 0
936         do
937                 case "$1" in
938                 -q|--quiet)
939                         GIT_QUIET=1
940                         shift
941                         ;;
942                 --)
943                         shift
944                         break
945                         ;;
946                 -*)
947                         usage
948                         ;;
949                 *)
950                         break
951                         ;;
952                 esac
953         done
954         cd_to_toplevel
955         module_list "$@" |
956         while read mode sha1 stage path
957         do
958                 name=$(module_name "$path")
959                 url=$(git config -f .gitmodules --get submodule."$name".url)
960
961                 # Possibly a url relative to parent
962                 case "$url" in
963                 ./*|../*)
964                         url=$(resolve_relative_url "$url") || exit
965                         ;;
966                 esac
967
968                 if git config "submodule.$name.url" >/dev/null 2>/dev/null
969                 then
970                         say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
971                         git config submodule."$name".url "$url"
972
973                         if test -e "$path"/.git
974                         then
975                         (
976                                 clear_local_git_env
977                                 cd "$path"
978                                 remote=$(get_default_remote)
979                                 git config remote."$remote".url "$url"
980                         )
981                         fi
982                 fi
983         done
984 }
985
986 # This loop parses the command line arguments to find the
987 # subcommand name to dispatch.  Parsing of the subcommand specific
988 # options are primarily done by the subcommand implementations.
989 # Subcommand specific options such as --branch and --cached are
990 # parsed here as well, for backward compatibility.
991
992 while test $# != 0 && test -z "$command"
993 do
994         case "$1" in
995         add | foreach | init | update | status | summary | sync)
996                 command=$1
997                 ;;
998         -q|--quiet)
999                 GIT_QUIET=1
1000                 ;;
1001         -b|--branch)
1002                 case "$2" in
1003                 '')
1004                         usage
1005                         ;;
1006                 esac
1007                 branch="$2"; shift
1008                 ;;
1009         --cached)
1010                 cached="$1"
1011                 ;;
1012         --)
1013                 break
1014                 ;;
1015         -*)
1016                 usage
1017                 ;;
1018         *)
1019                 break
1020                 ;;
1021         esac
1022         shift
1023 done
1024
1025 # No command word defaults to "status"
1026 test -n "$command" || command=status
1027
1028 # "-b branch" is accepted only by "add"
1029 if test -n "$branch" && test "$command" != add
1030 then
1031         usage
1032 fi
1033
1034 # "--cached" is accepted only by "status" and "summary"
1035 if test -n "$cached" && test "$command" != status -a "$command" != summary
1036 then
1037         usage
1038 fi
1039
1040 "cmd_$command" "$@"