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