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