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