]> git.ipfire.org Git - thirdparty/git.git/blob - git-submodule.sh
Sync with 2.34.8
[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 require_work_tree
24 wt_prefix=$(git rev-parse --show-prefix)
25 cd_to_toplevel
26
27 # Tell the rest of git that any URLs we get don't come
28 # directly from the user, so it can apply policy as appropriate.
29 GIT_PROTOCOL_FROM_USER=0
30 export GIT_PROTOCOL_FROM_USER
31
32 command=
33 branch=
34 force=
35 reference=
36 cached=
37 recursive=
38 init=
39 require_init=
40 files=
41 remote=
42 nofetch=
43 update=
44 prefix=
45 custom_name=
46 depth=
47 progress=
48 dissociate=
49 single_branch=
50 jobs=
51 recommend_shallow=
52
53 die_if_unmatched ()
54 {
55 if test "$1" = "#unmatched"
56 then
57 exit ${2:-1}
58 fi
59 }
60
61 isnumber()
62 {
63 n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
64 }
65
66 # Sanitize the local git environment for use within a submodule. We
67 # can't simply use clear_local_git_env since we want to preserve some
68 # of the settings from GIT_CONFIG_PARAMETERS.
69 sanitize_submodule_env()
70 {
71 save_config=$GIT_CONFIG_PARAMETERS
72 clear_local_git_env
73 GIT_CONFIG_PARAMETERS=$save_config
74 export GIT_CONFIG_PARAMETERS
75 }
76
77 #
78 # Add a new submodule to the working tree, .gitmodules and the index
79 #
80 # $@ = repo path
81 #
82 # optional branch is stored in global branch variable
83 #
84 cmd_add()
85 {
86 # parse $args after "submodule ... add".
87 reference_path=
88 while test $# -ne 0
89 do
90 case "$1" in
91 -b | --branch)
92 case "$2" in '') usage ;; esac
93 branch=$2
94 shift
95 ;;
96 -f | --force)
97 force=$1
98 ;;
99 -q|--quiet)
100 GIT_QUIET=1
101 ;;
102 --progress)
103 progress=1
104 ;;
105 --reference)
106 case "$2" in '') usage ;; esac
107 reference_path=$2
108 shift
109 ;;
110 --reference=*)
111 reference_path="${1#--reference=}"
112 ;;
113 --dissociate)
114 dissociate=1
115 ;;
116 --name)
117 case "$2" in '') usage ;; esac
118 custom_name=$2
119 shift
120 ;;
121 --depth)
122 case "$2" in '') usage ;; esac
123 depth="--depth=$2"
124 shift
125 ;;
126 --depth=*)
127 depth=$1
128 ;;
129 --)
130 shift
131 break
132 ;;
133 -*)
134 usage
135 ;;
136 *)
137 break
138 ;;
139 esac
140 shift
141 done
142
143 if test -z "$1"
144 then
145 usage
146 fi
147
148 git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
149 }
150
151 #
152 # Execute an arbitrary command sequence in each checked out
153 # submodule
154 #
155 # $@ = command to execute
156 #
157 cmd_foreach()
158 {
159 # parse $args after "submodule ... foreach".
160 while test $# -ne 0
161 do
162 case "$1" in
163 -q|--quiet)
164 GIT_QUIET=1
165 ;;
166 --recursive)
167 recursive=1
168 ;;
169 -*)
170 usage
171 ;;
172 *)
173 break
174 ;;
175 esac
176 shift
177 done
178
179 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
180 }
181
182 #
183 # Register submodules in .git/config
184 #
185 # $@ = requested paths (default to all)
186 #
187 cmd_init()
188 {
189 # parse $args after "submodule ... init".
190 while test $# -ne 0
191 do
192 case "$1" in
193 -q|--quiet)
194 GIT_QUIET=1
195 ;;
196 --)
197 shift
198 break
199 ;;
200 -*)
201 usage
202 ;;
203 *)
204 break
205 ;;
206 esac
207 shift
208 done
209
210 git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@"
211 }
212
213 #
214 # Unregister submodules from .git/config and remove their work tree
215 #
216 cmd_deinit()
217 {
218 # parse $args after "submodule ... deinit".
219 deinit_all=
220 while test $# -ne 0
221 do
222 case "$1" in
223 -f|--force)
224 force=$1
225 ;;
226 -q|--quiet)
227 GIT_QUIET=1
228 ;;
229 --all)
230 deinit_all=t
231 ;;
232 --)
233 shift
234 break
235 ;;
236 -*)
237 usage
238 ;;
239 *)
240 break
241 ;;
242 esac
243 shift
244 done
245
246 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
247 }
248
249 # usage: fetch_in_submodule <module_path> [<depth>] [<sha1>]
250 # Because arguments are positional, use an empty string to omit <depth>
251 # but include <sha1>.
252 fetch_in_submodule () (
253 sanitize_submodule_env &&
254 cd "$1" &&
255 if test $# -eq 3
256 then
257 echo "$3" | git fetch ${GIT_QUIET:+--quiet} --stdin ${2:+"$2"}
258 else
259 git fetch ${GIT_QUIET:+--quiet} ${2:+"$2"}
260 fi
261 )
262
263 #
264 # Update each submodule path to correct revision, using clone and checkout as needed
265 #
266 # $@ = requested paths (default to all)
267 #
268 cmd_update()
269 {
270 # parse $args after "submodule ... update".
271 while test $# -ne 0
272 do
273 case "$1" in
274 -q|--quiet)
275 GIT_QUIET=1
276 ;;
277 -v)
278 unset GIT_QUIET
279 ;;
280 --progress)
281 progress=1
282 ;;
283 -i|--init)
284 init=1
285 ;;
286 --require-init)
287 init=1
288 require_init=1
289 ;;
290 --remote)
291 remote=1
292 ;;
293 -N|--no-fetch)
294 nofetch=1
295 ;;
296 -f|--force)
297 force=$1
298 ;;
299 -r|--rebase)
300 update="rebase"
301 ;;
302 --reference)
303 case "$2" in '') usage ;; esac
304 reference="--reference=$2"
305 shift
306 ;;
307 --reference=*)
308 reference="$1"
309 ;;
310 --dissociate)
311 dissociate=1
312 ;;
313 -m|--merge)
314 update="merge"
315 ;;
316 --recursive)
317 recursive=1
318 ;;
319 --checkout)
320 update="checkout"
321 ;;
322 --recommend-shallow)
323 recommend_shallow="--recommend-shallow"
324 ;;
325 --no-recommend-shallow)
326 recommend_shallow="--no-recommend-shallow"
327 ;;
328 --depth)
329 case "$2" in '') usage ;; esac
330 depth="--depth=$2"
331 shift
332 ;;
333 --depth=*)
334 depth=$1
335 ;;
336 -j|--jobs)
337 case "$2" in '') usage ;; esac
338 jobs="--jobs=$2"
339 shift
340 ;;
341 --jobs=*)
342 jobs=$1
343 ;;
344 --single-branch)
345 single_branch="--single-branch"
346 ;;
347 --no-single-branch)
348 single_branch="--no-single-branch"
349 ;;
350 --)
351 shift
352 break
353 ;;
354 -*)
355 usage
356 ;;
357 *)
358 break
359 ;;
360 esac
361 shift
362 done
363
364 if test -n "$init"
365 then
366 cmd_init "--" "$@" || return
367 fi
368
369 {
370 git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
371 ${progress:+"--progress"} \
372 ${wt_prefix:+--prefix "$wt_prefix"} \
373 ${prefix:+--recursive-prefix "$prefix"} \
374 ${update:+--update "$update"} \
375 ${reference:+"$reference"} \
376 ${dissociate:+"--dissociate"} \
377 ${depth:+--depth "$depth"} \
378 ${require_init:+--require-init} \
379 $single_branch \
380 $recommend_shallow \
381 $jobs \
382 -- \
383 "$@" || echo "#unmatched" $?
384 } | {
385 err=
386 while read -r quickabort sha1 just_cloned sm_path
387 do
388 die_if_unmatched "$quickabort" "$sha1"
389
390 git submodule--helper ensure-core-worktree "$sm_path" || exit 1
391
392 displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
393
394 if test $just_cloned -eq 1
395 then
396 subsha1=
397 else
398 just_cloned=
399 subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
400 git rev-parse --verify HEAD) ||
401 die "fatal: $(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
402 fi
403
404 if test -n "$remote"
405 then
406 branch=$(git submodule--helper remote-branch "$sm_path")
407 if test -z "$nofetch"
408 then
409 # Fetch remote before determining tracking $sha1
410 fetch_in_submodule "$sm_path" $depth ||
411 die "fatal: $(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
412 fi
413 remote_name=$(sanitize_submodule_env; cd "$sm_path" && git submodule--helper print-default-remote)
414 sha1=$(sanitize_submodule_env; cd "$sm_path" &&
415 git rev-parse --verify "${remote_name}/${branch}") ||
416 die "fatal: $(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
417 fi
418
419 out=$(git submodule--helper run-update-procedure \
420 ${wt_prefix:+--prefix "$wt_prefix"} \
421 ${GIT_QUIET:+--quiet} \
422 ${force:+--force} \
423 ${just_cloned:+--just-cloned} \
424 ${nofetch:+--no-fetch} \
425 ${depth:+"$depth"} \
426 ${update:+--update "$update"} \
427 ${prefix:+--recursive-prefix "$prefix"} \
428 ${sha1:+--oid "$sha1"} \
429 ${subsha1:+--suboid "$subsha1"} \
430 "--" \
431 "$sm_path")
432
433 # exit codes for run-update-procedure:
434 # 0: update was successful, say command output
435 # 1: update procedure failed, but should not die
436 # 2 or 128: subcommand died during execution
437 # 3: no update procedure was run
438 res="$?"
439 case $res in
440 0)
441 say "$out"
442 ;;
443 1)
444 err="${err};fatal: $out"
445 continue
446 ;;
447 2|128)
448 die_with_status $res "fatal: $out"
449 ;;
450 esac
451
452 if test -n "$recursive"
453 then
454 (
455 prefix=$(git submodule--helper relative-path "$prefix$sm_path/" "$wt_prefix")
456 wt_prefix=
457 sanitize_submodule_env
458 cd "$sm_path" &&
459 eval cmd_update
460 )
461 res=$?
462 if test $res -gt 0
463 then
464 die_msg="fatal: $(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
465 if test $res -ne 2
466 then
467 err="${err};$die_msg"
468 continue
469 else
470 die_with_status $res "$die_msg"
471 fi
472 fi
473 fi
474 done
475
476 if test -n "$err"
477 then
478 OIFS=$IFS
479 IFS=';'
480 for e in $err
481 do
482 if test -n "$e"
483 then
484 echo >&2 "$e"
485 fi
486 done
487 IFS=$OIFS
488 exit 1
489 fi
490 }
491 }
492
493 #
494 # Configures a submodule's default branch
495 #
496 # $@ = requested path
497 #
498 cmd_set_branch() {
499 default=
500 branch=
501
502 while test $# -ne 0
503 do
504 case "$1" in
505 -q|--quiet)
506 # we don't do anything with this but we need to accept it
507 ;;
508 -d|--default)
509 default=1
510 ;;
511 -b|--branch)
512 case "$2" in '') usage ;; esac
513 branch=$2
514 shift
515 ;;
516 --)
517 shift
518 break
519 ;;
520 -*)
521 usage
522 ;;
523 *)
524 break
525 ;;
526 esac
527 shift
528 done
529
530 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@"
531 }
532
533 #
534 # Configures a submodule's remote url
535 #
536 # $@ = requested path, requested url
537 #
538 cmd_set_url() {
539 while test $# -ne 0
540 do
541 case "$1" in
542 -q|--quiet)
543 GIT_QUIET=1
544 ;;
545 --)
546 shift
547 break
548 ;;
549 -*)
550 usage
551 ;;
552 *)
553 break
554 ;;
555 esac
556 shift
557 done
558
559 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url ${GIT_QUIET:+--quiet} -- "$@"
560 }
561
562 #
563 # Show commit summary for submodules in index or working tree
564 #
565 # If '--cached' is given, show summary between index and given commit,
566 # or between working tree and given commit
567 #
568 # $@ = [commit (default 'HEAD'),] requested paths (default all)
569 #
570 cmd_summary() {
571 summary_limit=-1
572 for_status=
573 diff_cmd=diff-index
574
575 # parse $args after "submodule ... summary".
576 while test $# -ne 0
577 do
578 case "$1" in
579 --cached)
580 cached="$1"
581 ;;
582 --files)
583 files="$1"
584 ;;
585 --for-status)
586 for_status="$1"
587 ;;
588 -n|--summary-limit)
589 summary_limit="$2"
590 isnumber "$summary_limit" || usage
591 shift
592 ;;
593 --summary-limit=*)
594 summary_limit="${1#--summary-limit=}"
595 isnumber "$summary_limit" || usage
596 ;;
597 --)
598 shift
599 break
600 ;;
601 -*)
602 usage
603 ;;
604 *)
605 break
606 ;;
607 esac
608 shift
609 done
610
611 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper summary ${files:+--files} ${cached:+--cached} ${for_status:+--for-status} ${summary_limit:+-n $summary_limit} -- "$@"
612 }
613 #
614 # List all submodules, prefixed with:
615 # - submodule not initialized
616 # + different revision checked out
617 #
618 # If --cached was specified the revision in the index will be printed
619 # instead of the currently checked out revision.
620 #
621 # $@ = requested paths (default to all)
622 #
623 cmd_status()
624 {
625 # parse $args after "submodule ... status".
626 while test $# -ne 0
627 do
628 case "$1" in
629 -q|--quiet)
630 GIT_QUIET=1
631 ;;
632 --cached)
633 cached=1
634 ;;
635 --recursive)
636 recursive=1
637 ;;
638 --)
639 shift
640 break
641 ;;
642 -*)
643 usage
644 ;;
645 *)
646 break
647 ;;
648 esac
649 shift
650 done
651
652 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@"
653 }
654 #
655 # Sync remote urls for submodules
656 # This makes the value for remote.$remote.url match the value
657 # specified in .gitmodules.
658 #
659 cmd_sync()
660 {
661 while test $# -ne 0
662 do
663 case "$1" in
664 -q|--quiet)
665 GIT_QUIET=1
666 shift
667 ;;
668 --recursive)
669 recursive=1
670 shift
671 ;;
672 --)
673 shift
674 break
675 ;;
676 -*)
677 usage
678 ;;
679 *)
680 break
681 ;;
682 esac
683 done
684
685 git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
686 }
687
688 cmd_absorbgitdirs()
689 {
690 git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@"
691 }
692
693 # This loop parses the command line arguments to find the
694 # subcommand name to dispatch. Parsing of the subcommand specific
695 # options are primarily done by the subcommand implementations.
696 # Subcommand specific options such as --branch and --cached are
697 # parsed here as well, for backward compatibility.
698
699 while test $# != 0 && test -z "$command"
700 do
701 case "$1" in
702 add | foreach | init | deinit | update | set-branch | set-url | status | summary | sync | absorbgitdirs)
703 command=$1
704 ;;
705 -q|--quiet)
706 GIT_QUIET=1
707 ;;
708 -b|--branch)
709 case "$2" in
710 '')
711 usage
712 ;;
713 esac
714 branch="$2"; shift
715 ;;
716 --cached)
717 cached="$1"
718 ;;
719 --)
720 break
721 ;;
722 -*)
723 usage
724 ;;
725 *)
726 break
727 ;;
728 esac
729 shift
730 done
731
732 # No command word defaults to "status"
733 if test -z "$command"
734 then
735 if test $# = 0
736 then
737 command=status
738 else
739 usage
740 fi
741 fi
742
743 # "-b branch" is accepted only by "add" and "set-branch"
744 if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
745 then
746 usage
747 fi
748
749 # "--cached" is accepted only by "status" and "summary"
750 if test -n "$cached" && test "$command" != status && test "$command" != summary
751 then
752 usage
753 fi
754
755 "cmd_$(echo $command | sed -e s/-/_/g)" "$@"