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