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