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