Code

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